• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 /*
28  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
29  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
30  *
31  *   The original version of this source code and documentation is copyrighted
32  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
33  * materials are provided under terms of a License Agreement between Taligent
34  * and Sun. This technology is protected by multiple US and International
35  * patents. This notice and attribution to Taligent may not be removed.
36  *   Taligent is a registered trademark of Taligent, Inc.
37  *
38  */
39 
40 package java.text;
41 
42 import java.io.IOException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.io.ObjectStreamField;
46 import java.math.BigDecimal;
47 import java.math.BigInteger;
48 import java.math.RoundingMode;
49 import java.util.Currency;
50 import java.util.Locale;
51 import java.util.Objects;
52 import java.util.concurrent.atomic.AtomicInteger;
53 import java.util.concurrent.atomic.AtomicLong;
54 import libcore.icu.DecimalFormatData;
55 import libcore.icu.LocaleData;
56 import android.icu.math.MathContext;
57 
58 import com.android.icu.text.CompatibleDecimalFormatFactory;
59 
60 /**
61  * <code>DecimalFormat</code> is a concrete subclass of
62  * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
63  * features designed to make it possible to parse and format numbers in any
64  * locale, including support for Western, Arabic, and Indic digits.  It also
65  * supports different kinds of numbers, including integers (123), fixed-point
66  * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
67  * currency amounts ($123).  All of these can be localized.
68  *
69  * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
70  * default locale, call one of <code>NumberFormat</code>'s factory methods, such
71  * as <code>getInstance()</code>.  In general, do not call the
72  * <code>DecimalFormat</code> constructors directly, since the
73  * <code>NumberFormat</code> factory methods may return subclasses other than
74  * <code>DecimalFormat</code>. If you need to customize the format object, do
75  * something like this:
76  *
77  * <blockquote><pre>
78  * NumberFormat f = NumberFormat.getInstance(loc);
79  * if (f instanceof DecimalFormat) {
80  *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
81  * }
82  * </pre></blockquote>
83  *
84  * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
85  * <em>symbols</em>.  The pattern may be set directly using
86  * <code>applyPattern()</code>, or indirectly using the API methods.  The
87  * symbols are stored in a <code>DecimalFormatSymbols</code> object.  When using
88  * the <code>NumberFormat</code> factory methods, the pattern and symbols are
89  * read from localized <code>ResourceBundle</code>s.
90  *
91  * <h3>Patterns</h3>
92  *
93  * <code>DecimalFormat</code> patterns have the following syntax:
94  * <blockquote><pre>
95  * <i>Pattern:</i>
96  *         <i>PositivePattern</i>
97  *         <i>PositivePattern</i> ; <i>NegativePattern</i>
98  * <i>PositivePattern:</i>
99  *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
100  * <i>NegativePattern:</i>
101  *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
102  * <i>Prefix:</i>
103  *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
104  * <i>Suffix:</i>
105  *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
106  * <i>Number:</i>
107  *         <i>Integer</i> <i>Exponent<sub>opt</sub></i>
108  *         <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
109  * <i>Integer:</i>
110  *         <i>MinimumInteger</i>
111  *         #
112  *         # <i>Integer</i>
113  *         # , <i>Integer</i>
114  * <i>MinimumInteger:</i>
115  *         0
116  *         0 <i>MinimumInteger</i>
117  *         0 , <i>MinimumInteger</i>
118  * <i>Fraction:</i>
119  *         <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
120  * <i>MinimumFraction:</i>
121  *         0 <i>MinimumFraction<sub>opt</sub></i>
122  * <i>OptionalFraction:</i>
123  *         # <i>OptionalFraction<sub>opt</sub></i>
124  * <i>Exponent:</i>
125  *         E <i>MinimumExponent</i>
126  * <i>MinimumExponent:</i>
127  *         0 <i>MinimumExponent<sub>opt</sub></i>
128  * </pre></blockquote>
129  *
130  * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
131  * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>.  Each
132  * subpattern has a prefix, numeric part, and suffix. The negative subpattern
133  * is optional; if absent, then the positive subpattern prefixed with the
134  * localized minus sign (<code>'-'</code> in most locales) is used as the
135  * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
136  * <code>"0.00;-0.00"</code>.  If there is an explicit negative subpattern, it
137  * serves only to specify the negative prefix and suffix; the number of digits,
138  * minimal digits, and other characteristics are all the same as the positive
139  * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
140  * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
141  *
142  * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
143  * thousands separators, decimal separators, etc. may be set to arbitrary
144  * values, and they will appear properly during formatting.  However, care must
145  * be taken that the symbols and strings do not conflict, or parsing will be
146  * unreliable.  For example, either the positive and negative prefixes or the
147  * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
148  * to distinguish positive from negative values.  (If they are identical, then
149  * <code>DecimalFormat</code> will behave as if no negative subpattern was
150  * specified.)  Another example is that the decimal separator and thousands
151  * separator should be distinct characters, or parsing will be impossible.
152  *
153  * <p>The grouping separator is commonly used for thousands, but in some
154  * countries it separates ten-thousands. The grouping size is a constant number
155  * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
156  * 1,0000,0000.  If you supply a pattern with multiple grouping characters, the
157  * interval between the last one and the end of the integer is the one that is
158  * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
159  * <code>"##,####,####"</code>.
160  *
161  * <h4>Special Pattern Characters</h4>
162  *
163  * <p>Many characters in a pattern are taken literally; they are matched during
164  * parsing and output unchanged during formatting.  Special characters, on the
165  * other hand, stand for other characters, strings, or classes of characters.
166  * They must be quoted, unless noted otherwise, if they are to appear in the
167  * prefix or suffix as literals.
168  *
169  * <p>The characters listed here are used in non-localized patterns.  Localized
170  * patterns use the corresponding characters taken from this formatter's
171  * <code>DecimalFormatSymbols</code> object instead, and these characters lose
172  * their special status.  Two exceptions are the currency sign and quote, which
173  * are not localized.
174  *
175  * <blockquote>
176  * <table class="striped">
177  * <caption style="display:none">Chart showing symbol, location, localized, and meaning.</caption>
178  * <thead>
179  *     <tr>
180  *          <th scope="col" style="text-align:left">Symbol
181  *          <th scope="col" style="text-align:left">Location
182  *          <th scope="col" style="text-align:left">Localized?
183  *          <th scope="col" style="text-align:left">Meaning
184  * </thead>
185  * <tbody>
186  *     <tr style="vertical-align:top">
187  *          <th scope="row"><code>0</code>
188  *          <td>Number
189  *          <td>Yes
190  *          <td>Digit
191  *     <tr style="vertical-align: top">
192  *          <th scope="row"><code>#</code>
193  *          <td>Number
194  *          <td>Yes
195  *          <td>Digit, zero shows as absent
196  *     <tr style="vertical-align:top">
197  *          <th scope="row"><code>.</code>
198  *          <td>Number
199  *          <td>Yes
200  *          <td>Decimal separator or monetary decimal separator
201  *     <tr style="vertical-align: top">
202  *          <th scope="row"><code>-</code>
203  *          <td>Number
204  *          <td>Yes
205  *          <td>Minus sign
206  *     <tr style="vertical-align:top">
207  *          <th scope="row"><code>,</code>
208  *          <td>Number
209  *          <td>Yes
210  *          <td>Grouping separator
211  *     <tr style="vertical-align: top">
212  *          <th scope="row"><code>E</code>
213  *          <td>Number
214  *          <td>Yes
215  *          <td>Separates mantissa and exponent in scientific notation.
216  *              <em>Need not be quoted in prefix or suffix.</em>
217  *     <tr style="vertical-align:top">
218  *          <th scope="row"><code>;</code>
219  *          <td>Subpattern boundary
220  *          <td>Yes
221  *          <td>Separates positive and negative subpatterns
222  *     <tr style="vertical-align: top">
223  *          <th scope="row"><code>%</code>
224  *          <td>Prefix or suffix
225  *          <td>Yes
226  *          <td>Multiply by 100 and show as percentage
227  *     <tr style="vertical-align:top">
228  *          <th scope="row"><code>&#92;u2030</code>
229  *          <td>Prefix or suffix
230  *          <td>Yes
231  *          <td>Multiply by 1000 and show as per mille value
232  *     <tr style="vertical-align: top">
233  *          <th scope="row"><code>&#164;</code> (<code>&#92;u00A4</code>)
234  *          <td>Prefix or suffix
235  *          <td>No
236  *          <td>Currency sign, replaced by currency symbol.  If
237  *              doubled, replaced by international currency symbol.
238  *              If present in a pattern, the monetary decimal separator
239  *              is used instead of the decimal separator.
240  *     <tr style="vertical-align:top">
241  *          <th scope="row"><code>'</code>
242  *          <td>Prefix or suffix
243  *          <td>No
244  *          <td>Used to quote special characters in a prefix or suffix,
245  *              for example, <code>"'#'#"</code> formats 123 to
246  *              <code>"#123"</code>.  To create a single quote
247  *              itself, use two in a row: <code>"# o''clock"</code>.
248  * </tbody>
249  * </table>
250  * </blockquote>
251  *
252  * <h4>Scientific Notation</h4>
253  *
254  * <p>Numbers in scientific notation are expressed as the product of a mantissa
255  * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3.  The
256  * mantissa is often in the range 1.0 &le; x {@literal <} 10.0, but it need not
257  * be.
258  * <code>DecimalFormat</code> can be instructed to format and parse scientific
259  * notation <em>only via a pattern</em>; there is currently no factory method
260  * that creates a scientific notation format.  In a pattern, the exponent
261  * character immediately followed by one or more digit characters indicates
262  * scientific notation.  Example: <code>"0.###E0"</code> formats the number
263  * 1234 as <code>"1.234E3"</code>.
264  *
265  * <ul>
266  * <li>The number of digit characters after the exponent character gives the
267  * minimum exponent digit count.  There is no maximum.  Negative exponents are
268  * formatted using the localized minus sign, <em>not</em> the prefix and suffix
269  * from the pattern.  This allows patterns such as <code>"0.###E0 m/s"</code>.
270  *
271  * <li>The minimum and maximum number of integer digits are interpreted
272  * together:
273  *
274  * <ul>
275  * <li>If the maximum number of integer digits is greater than their minimum number
276  * and greater than 1, it forces the exponent to be a multiple of the maximum
277  * number of integer digits, and the minimum number of integer digits to be
278  * interpreted as 1.  The most common use of this is to generate
279  * <em>engineering notation</em>, in which the exponent is a multiple of three,
280  * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
281  * formats to <code>"12.345E3"</code>, and 123456 formats to
282  * <code>"123.456E3"</code>.
283  *
284  * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
285  * exponent.  Example: 0.00123 formatted with <code>"00.###E0"</code> yields
286  * <code>"12.3E-4"</code>.
287  * </ul>
288  *
289  * <li>The number of significant digits in the mantissa is the sum of the
290  * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
291  * unaffected by the maximum integer digits.  For example, 12345 formatted with
292  * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
293  * the significant digits count to zero.  The number of significant digits
294  * does not affect parsing.
295  *
296  * <li>Exponential patterns may not contain grouping separators.
297  * </ul>
298  *
299  * <h4>Rounding</h4>
300  *
301  * <code>DecimalFormat</code> provides rounding modes defined in
302  * {@link java.math.RoundingMode} for formatting.  By default, it uses
303  * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
304  *
305  * <h4>Digits</h4>
306  *
307  * For formatting, <code>DecimalFormat</code> uses the ten consecutive
308  * characters starting with the localized zero digit defined in the
309  * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
310  * digits as well as all Unicode decimal digits, as defined by
311  * {@link Character#digit Character.digit}, are recognized.
312  *
313  * <h4>Special Values</h4>
314  *
315  * <p><code>NaN</code> is formatted as a string, which typically has a single character
316  * <code>&#92;uFFFD</code>.  This string is determined by the
317  * <code>DecimalFormatSymbols</code> object.  This is the only value for which
318  * the prefixes and suffixes are not used.
319  *
320  * <p>Infinity is formatted as a string, which typically has a single character
321  * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
322  * applied.  The infinity string is determined by the
323  * <code>DecimalFormatSymbols</code> object.
324  *
325  * <p>Negative zero (<code>"-0"</code>) parses to
326  * <ul>
327  * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
328  * true,
329  * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
330  *     and <code>isParseIntegerOnly()</code> is true,
331  * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
332  * and <code>isParseIntegerOnly()</code> are false.
333  * </ul>
334  *
335  * <h4><a id="synchronization">Synchronization</a></h4>
336  *
337  * <p>
338  * Decimal formats are generally not synchronized.
339  * It is recommended to create separate format instances for each thread.
340  * If multiple threads access a format concurrently, it must be synchronized
341  * externally.
342  *
343  * <h4>Example</h4>
344  *
345  * <blockquote><pre>{@code
346  * <strong>// Print out a number using the localized number, integer, currency,
347  * // and percent format for each locale</strong>
348  * Locale[] locales = NumberFormat.getAvailableLocales();
349  * double myNumber = -1234.56;
350  * NumberFormat form;
351  * for (int j = 0; j < 4; ++j) {
352  *     System.out.println("FORMAT");
353  *     for (int i = 0; i < locales.length; ++i) {
354  *         if (locales[i].getCountry().length() == 0) {
355  *            continue; // Skip language-only locales
356  *         }
357  *         System.out.print(locales[i].getDisplayName());
358  *         switch (j) {
359  *         case 0:
360  *             form = NumberFormat.getInstance(locales[i]); break;
361  *         case 1:
362  *             form = NumberFormat.getIntegerInstance(locales[i]); break;
363  *         case 2:
364  *             form = NumberFormat.getCurrencyInstance(locales[i]); break;
365  *         default:
366  *             form = NumberFormat.getPercentInstance(locales[i]); break;
367  *         }
368  *         if (form instanceof DecimalFormat) {
369  *             System.out.print(": " + ((DecimalFormat) form).toPattern());
370  *         }
371  *         System.out.print(" -> " + form.format(myNumber));
372  *         try {
373  *             System.out.println(" -> " + form.parse(form.format(myNumber)));
374  *         } catch (ParseException e) {}
375  *     }
376  * }
377  * }</pre></blockquote>
378  *
379  * @see          <a href="http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
380  * @see          NumberFormat
381  * @see          DecimalFormatSymbols
382  * @see          ParsePosition
383  * @author       Mark Davis
384  * @author       Alan Liu
385  * @since 1.1
386  */
387 public class DecimalFormat extends NumberFormat {
388 
389     // Android-note: This class is heavily modified from upstream OpenJDK.
390     // Android's version delegates most of its work to android.icu.text.DecimalFormat. This is done
391     // to avoid code duplication and to stay compatible with earlier releases that used ICU4C/ICU4J
392     // to implement DecimalFormat.
393 
394     // Android-added: ICU DecimalFormat to delegate to.
395     private transient android.icu.text.DecimalFormat icuDecimalFormat;
396 
397     /**
398      * Creates a DecimalFormat using the default pattern and symbols
399      * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.
400      * This is a convenient way to obtain a
401      * DecimalFormat when internationalization is not the main concern.
402      * <p>
403      * To obtain standard formats for a given locale, use the factory methods
404      * on NumberFormat such as getNumberInstance. These factories will
405      * return the most appropriate sub-class of NumberFormat for a given
406      * locale.
407      *
408      * @see java.text.NumberFormat#getInstance
409      * @see java.text.NumberFormat#getNumberInstance
410      * @see java.text.NumberFormat#getCurrencyInstance
411      * @see java.text.NumberFormat#getPercentInstance
412      */
DecimalFormat()413     public DecimalFormat() {
414         // Get the pattern for the default locale.
415         Locale def = Locale.getDefault(Locale.Category.FORMAT);
416         // BEGIN Android-changed: Use ICU LocaleData. Remove SPI LocaleProviderAdapter.
417         /*
418         LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
419         if (!(adapter instanceof ResourceBundleBasedAdapter)) {
420             adapter = LocaleProviderAdapter.getResourceBundleBased();
421         }
422         String[] all = adapter.getLocaleResources(def).getNumberPatterns();
423         */
424         String pattern = DecimalFormatData.getInstance(def).getNumberPattern();
425         // END Android-changed: Use ICU LocaleData. Remove SPI LocaleProviderAdapter.
426 
427         // Always applyPattern after the symbols are set
428         this.symbols = DecimalFormatSymbols.getInstance(def);
429         // Android-changed: initPattern() and conversion methods between ICU and Java values.
430         // applyPattern(all[0], false);
431         initPattern(pattern);
432     }
433 
434 
435     /**
436      * Creates a DecimalFormat using the given pattern and the symbols
437      * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.
438      * This is a convenient way to obtain a
439      * DecimalFormat when internationalization is not the main concern.
440      * <p>
441      * To obtain standard formats for a given locale, use the factory methods
442      * on NumberFormat such as getNumberInstance. These factories will
443      * return the most appropriate sub-class of NumberFormat for a given
444      * locale.
445      *
446      * @param pattern a non-localized pattern string.
447      * @exception NullPointerException if <code>pattern</code> is null
448      * @exception IllegalArgumentException if the given pattern is invalid.
449      * @see java.text.NumberFormat#getInstance
450      * @see java.text.NumberFormat#getNumberInstance
451      * @see java.text.NumberFormat#getCurrencyInstance
452      * @see java.text.NumberFormat#getPercentInstance
453      */
DecimalFormat(String pattern)454     public DecimalFormat(String pattern) {
455         // Always applyPattern after the symbols are set
456         this.symbols = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));
457         // Android-changed: initPattern() and conversion methods between ICU and Java values.
458         // applyPattern(pattern, false);
459         initPattern(pattern);
460     }
461 
462 
463     /**
464      * Creates a DecimalFormat using the given pattern and symbols.
465      * Use this constructor when you need to completely customize the
466      * behavior of the format.
467      * <p>
468      * To obtain standard formats for a given
469      * locale, use the factory methods on NumberFormat such as
470      * getInstance or getCurrencyInstance. If you need only minor adjustments
471      * to a standard format, you can modify the format returned by
472      * a NumberFormat factory method.
473      *
474      * @param pattern a non-localized pattern string
475      * @param symbols the set of symbols to be used
476      * @exception NullPointerException if any of the given arguments is null
477      * @exception IllegalArgumentException if the given pattern is invalid
478      * @see java.text.NumberFormat#getInstance
479      * @see java.text.NumberFormat#getNumberInstance
480      * @see java.text.NumberFormat#getCurrencyInstance
481      * @see java.text.NumberFormat#getPercentInstance
482      * @see java.text.DecimalFormatSymbols
483      */
DecimalFormat(String pattern, DecimalFormatSymbols symbols)484     public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
485         // Always applyPattern after the symbols are set
486         this.symbols = (DecimalFormatSymbols)symbols.clone();
487         // Android-changed: initPattern() and conversion methods between ICU and Java values.
488         initPattern(pattern);
489     }
490 
491     // BEGIN Android-added: initPattern() and conversion methods between ICU and Java values.
492     /**
493      * Applies the pattern similarly to {@link #applyPattern(String)}, except it initializes
494      * {@link #icuDecimalFormat} in the process. This should only be called from constructors.
495      */
initPattern(String pattern)496     private void initPattern(String pattern) {
497         // Android-changed: Compatibility mode for j.t.DecimalFormat. http://b/112355520
498         this.icuDecimalFormat = CompatibleDecimalFormatFactory.create(pattern,
499                 symbols.getIcuDecimalFormatSymbols());
500         updateFieldsFromIcu();
501     }
502 
503     /**
504      * Update local fields indicating maximum/minimum integer/fraction digit count from the ICU
505      * DecimalFormat. This needs to be called whenever a new pattern is applied.
506      */
updateFieldsFromIcu()507     private void updateFieldsFromIcu() {
508         // Imitate behaviour of ICU4C NumberFormat that Android used up to M.
509         // If the pattern doesn't enforce a different value (some exponential
510         // patterns do), then set the maximum integer digits to 2 billion.
511         if (icuDecimalFormat.getMaximumIntegerDigits() == DOUBLE_INTEGER_DIGITS) {
512             icuDecimalFormat.setMaximumIntegerDigits(2000000000);
513         }
514         maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
515         minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
516         maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
517         minimumFractionDigits = icuDecimalFormat.getMinimumFractionDigits();
518     }
519 
520     /**
521      * Converts between field positions used by Java/ICU.
522      * @param fp The java.text.NumberFormat.Field field position
523      * @return The android.icu.text.NumberFormat.Field field position
524      */
getIcuFieldPosition(FieldPosition fp)525     private static FieldPosition getIcuFieldPosition(FieldPosition fp) {
526         Format.Field fieldAttribute = fp.getFieldAttribute();
527         if (fieldAttribute == null) return fp;
528 
529         android.icu.text.NumberFormat.Field attribute;
530         if (fieldAttribute == Field.INTEGER) {
531             attribute = android.icu.text.NumberFormat.Field.INTEGER;
532         } else if (fieldAttribute == Field.FRACTION) {
533             attribute = android.icu.text.NumberFormat.Field.FRACTION;
534         } else if (fieldAttribute == Field.DECIMAL_SEPARATOR) {
535             attribute = android.icu.text.NumberFormat.Field.DECIMAL_SEPARATOR;
536         } else if (fieldAttribute == Field.EXPONENT_SYMBOL) {
537             attribute = android.icu.text.NumberFormat.Field.EXPONENT_SYMBOL;
538         } else if (fieldAttribute == Field.EXPONENT_SIGN) {
539             attribute = android.icu.text.NumberFormat.Field.EXPONENT_SIGN;
540         } else if (fieldAttribute == Field.EXPONENT) {
541             attribute = android.icu.text.NumberFormat.Field.EXPONENT;
542         } else if (fieldAttribute == Field.GROUPING_SEPARATOR) {
543             attribute = android.icu.text.NumberFormat.Field.GROUPING_SEPARATOR;
544         } else if (fieldAttribute == Field.CURRENCY) {
545             attribute = android.icu.text.NumberFormat.Field.CURRENCY;
546         } else if (fieldAttribute == Field.PERCENT) {
547             attribute = android.icu.text.NumberFormat.Field.PERCENT;
548         } else if (fieldAttribute == Field.PERMILLE) {
549             attribute = android.icu.text.NumberFormat.Field.PERMILLE;
550         } else if (fieldAttribute == Field.SIGN) {
551             attribute = android.icu.text.NumberFormat.Field.SIGN;
552         } else {
553             throw new IllegalArgumentException("Unexpected field position attribute type.");
554         }
555 
556         FieldPosition icuFieldPosition = new FieldPosition(attribute);
557         icuFieldPosition.setBeginIndex(fp.getBeginIndex());
558         icuFieldPosition.setEndIndex(fp.getEndIndex());
559         return icuFieldPosition;
560     }
561 
562     /**
563      * Converts the Attribute that ICU returns in its AttributedCharacterIterator
564      * responses to the type that java uses.
565      * @param icuAttribute The AttributedCharacterIterator.Attribute field.
566      * @return Field converted to a java.text.NumberFormat.Field field.
567      */
toJavaFieldAttribute(AttributedCharacterIterator.Attribute icuAttribute)568     private static Field toJavaFieldAttribute(AttributedCharacterIterator.Attribute icuAttribute) {
569         String name = icuAttribute.getName();
570         if (name.equals(Field.INTEGER.getName())) {
571             return Field.INTEGER;
572         }
573         if (name.equals(Field.CURRENCY.getName())) {
574             return Field.CURRENCY;
575         }
576         if (name.equals(Field.DECIMAL_SEPARATOR.getName())) {
577             return Field.DECIMAL_SEPARATOR;
578         }
579         if (name.equals(Field.EXPONENT.getName())) {
580             return Field.EXPONENT;
581         }
582         if (name.equals(Field.EXPONENT_SIGN.getName())) {
583             return Field.EXPONENT_SIGN;
584         }
585         if (name.equals(Field.EXPONENT_SYMBOL.getName())) {
586             return Field.EXPONENT_SYMBOL;
587         }
588         if (name.equals(Field.FRACTION.getName())) {
589             return Field.FRACTION;
590         }
591         if (name.equals(Field.GROUPING_SEPARATOR.getName())) {
592             return Field.GROUPING_SEPARATOR;
593         }
594         if (name.equals(Field.SIGN.getName())) {
595             return Field.SIGN;
596         }
597         if (name.equals(Field.PERCENT.getName())) {
598             return Field.PERCENT;
599         }
600         if (name.equals(Field.PERMILLE.getName())) {
601             return Field.PERMILLE;
602         }
603         throw new IllegalArgumentException("Unrecognized attribute: " + name);
604     }
605     // END Android-added: initPattern() and conversion methods between ICU and Java values.
606 
607     // Overrides
608     /**
609      * Formats a number and appends the resulting text to the given string
610      * buffer.
611      * The number can be of any subclass of {@link java.lang.Number}.
612      * <p>
613      * This implementation uses the maximum precision permitted.
614      * @param number     the number to format
615      * @param toAppendTo the <code>StringBuffer</code> to which the formatted
616      *                   text is to be appended
617      * @param pos        keeps track on the position of the field within the
618      *                   returned string. For example, for formatting a number
619      *                   {@code 1234567.89} in {@code Locale.US} locale,
620      *                   if the given {@code fieldPosition} is
621      *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
622      *                   and end index of {@code fieldPosition} will be set
623      *                   to 0 and 9, respectively for the output string
624      *                   {@code 1,234,567.89}.
625      * @return           the value passed in as <code>toAppendTo</code>
626      * @exception        IllegalArgumentException if <code>number</code> is
627      *                   null or not an instance of <code>Number</code>.
628      * @exception        NullPointerException if <code>toAppendTo</code> or
629      *                   <code>pos</code> is null
630      * @exception        ArithmeticException if rounding is needed with rounding
631      *                   mode being set to RoundingMode.UNNECESSARY
632      * @see              java.text.FieldPosition
633      */
634     @Override
format(Object number, StringBuffer toAppendTo, FieldPosition pos)635     public final StringBuffer format(Object number,
636                                      StringBuffer toAppendTo,
637                                      FieldPosition pos) {
638         if (number instanceof Long || number instanceof Integer ||
639                    number instanceof Short || number instanceof Byte ||
640                    number instanceof AtomicInteger ||
641                    number instanceof AtomicLong ||
642                    (number instanceof BigInteger &&
643                     ((BigInteger)number).bitLength () < 64)) {
644             return format(((Number)number).longValue(), toAppendTo, pos);
645         } else if (number instanceof BigDecimal) {
646             return format((BigDecimal)number, toAppendTo, pos);
647         } else if (number instanceof BigInteger) {
648             return format((BigInteger)number, toAppendTo, pos);
649         } else if (number instanceof Number) {
650             return format(((Number)number).doubleValue(), toAppendTo, pos);
651         } else {
652             throw new IllegalArgumentException("Cannot format given Object as a Number");
653         }
654     }
655 
656     /**
657      * Formats a double to produce a string.
658      * @param number    The double to format
659      * @param result    where the text is to be appended
660      * @param fieldPosition    keeps track on the position of the field within
661      *                         the returned string. For example, for formatting
662      *                         a number {@code 1234567.89} in {@code Locale.US}
663      *                         locale, if the given {@code fieldPosition} is
664      *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
665      *                         and end index of {@code fieldPosition} will be set
666      *                         to 0 and 9, respectively for the output string
667      *                         {@code 1,234,567.89}.
668      * @exception NullPointerException if {@code result} or
669      *            {@code fieldPosition} is {@code null}
670      * @exception ArithmeticException if rounding is needed with rounding
671      *            mode being set to RoundingMode.UNNECESSARY
672      * @return The formatted number string
673      * @see java.text.FieldPosition
674      */
675     @Override
format(double number, StringBuffer result, FieldPosition fieldPosition)676     public StringBuffer format(double number, StringBuffer result,
677                                FieldPosition fieldPosition) {
678         // BEGIN Android-changed: Use ICU.
679         /*
680         // If fieldPosition is a DontCareFieldPosition instance we can
681         // try to go to fast-path code.
682         boolean tryFastPath = false;
683         if (fieldPosition == DontCareFieldPosition.INSTANCE)
684             tryFastPath = true;
685         else {
686             fieldPosition.setBeginIndex(0);
687             fieldPosition.setEndIndex(0);
688         }
689 
690         if (tryFastPath) {
691             String tempResult = fastFormat(number);
692             if (tempResult != null) {
693                 result.append(tempResult);
694                 return result;
695             }
696         }
697 
698         // if fast-path could not work, we fallback to standard code.
699         return format(number, result, fieldPosition.getFieldDelegate());
700         */
701         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
702         icuDecimalFormat.format(number, result, icuFieldPosition);
703         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
704         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
705         return result;
706         // END Android-changed: Use ICU.
707     }
708 
709     // BEGIN Android-removed: Use ICU.
710     // Removed unused helper function that was only used from (unused on Android) code
711     // in format(double, StringBuffer, FieldPosition).
712     /*
713     /**
714      * Formats a double to produce a string.
715      * @param number    The double to format
716      * @param result    where the text is to be appended
717      * @param delegate notified of locations of sub fields
718      * @exception       ArithmeticException if rounding is needed with rounding
719      *                  mode being set to RoundingMode.UNNECESSARY
720      * @return The formatted number string
721      *
722     private StringBuffer format(double number, StringBuffer result,
723                                 FieldDelegate delegate) {
724         if (Double.isNaN(number) ||
725            (Double.isInfinite(number) && multiplier == 0)) {
726             int iFieldStart = result.length();
727             result.append(symbols.getNaN());
728             delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
729                                iFieldStart, result.length(), result);
730             return result;
731         }
732 
733         /* Detecting whether a double is negative is easy with the exception of
734          * the value -0.0.  This is a double which has a zero mantissa (and
735          * exponent), but a negative sign bit.  It is semantically distinct from
736          * a zero with a positive sign bit, and this distinction is important
737          * to certain kinds of computations.  However, it's a little tricky to
738          * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0).  How then, you may
739          * ask, does it behave distinctly from +0.0?  Well, 1/(-0.0) ==
740          * -Infinity.  Proper detection of -0.0 is needed to deal with the
741          * issues raised by bugs 4106658, 4106667, and 4147706.  Liu 7/6/98.
742          *
743         boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0);
744 
745         if (multiplier != 1) {
746             number *= multiplier;
747         }
748 
749         if (Double.isInfinite(number)) {
750             if (isNegative) {
751                 append(result, negativePrefix, delegate,
752                        getNegativePrefixFieldPositions(), Field.SIGN);
753             } else {
754                 append(result, positivePrefix, delegate,
755                        getPositivePrefixFieldPositions(), Field.SIGN);
756             }
757 
758             int iFieldStart = result.length();
759             result.append(symbols.getInfinity());
760             delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
761                                iFieldStart, result.length(), result);
762 
763             if (isNegative) {
764                 append(result, negativeSuffix, delegate,
765                        getNegativeSuffixFieldPositions(), Field.SIGN);
766             } else {
767                 append(result, positiveSuffix, delegate,
768                        getPositiveSuffixFieldPositions(), Field.SIGN);
769             }
770 
771             return result;
772         }
773 
774         if (isNegative) {
775             number = -number;
776         }
777 
778         // at this point we are guaranteed a nonnegative finite number.
779         assert(number >= 0 && !Double.isInfinite(number));
780 
781         synchronized(digitList) {
782             int maxIntDigits = super.getMaximumIntegerDigits();
783             int minIntDigits = super.getMinimumIntegerDigits();
784             int maxFraDigits = super.getMaximumFractionDigits();
785             int minFraDigits = super.getMinimumFractionDigits();
786 
787             digitList.set(isNegative, number, useExponentialNotation ?
788                           maxIntDigits + maxFraDigits : maxFraDigits,
789                           !useExponentialNotation);
790             return subformat(result, delegate, isNegative, false,
791                        maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
792         }
793     }
794     */
795     // END Android-removed: Use ICU.
796 
797     /**
798      * Format a long to produce a string.
799      * @param number    The long to format
800      * @param result    where the text is to be appended
801      * @param fieldPosition    keeps track on the position of the field within
802      *                         the returned string. For example, for formatting
803      *                         a number {@code 123456789} in {@code Locale.US}
804      *                         locale, if the given {@code fieldPosition} is
805      *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
806      *                         and end index of {@code fieldPosition} will be set
807      *                         to 0 and 11, respectively for the output string
808      *                         {@code 123,456,789}.
809      * @exception       NullPointerException if {@code result} or
810      *                  {@code fieldPosition} is {@code null}
811      * @exception       ArithmeticException if rounding is needed with rounding
812      *                  mode being set to RoundingMode.UNNECESSARY
813      * @return The formatted number string
814      * @see java.text.FieldPosition
815      */
816     @Override
format(long number, StringBuffer result, FieldPosition fieldPosition)817     public StringBuffer format(long number, StringBuffer result,
818                                FieldPosition fieldPosition) {
819         // BEGIN Android-changed: Use ICU.
820         /*
821         fieldPosition.setBeginIndex(0);
822         fieldPosition.setEndIndex(0);
823 
824         return format(number, result, fieldPosition.getFieldDelegate());
825         */
826         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
827         icuDecimalFormat.format(number, result, icuFieldPosition);
828         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
829         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
830         return result;
831         // END Android-changed: Use ICU.
832     }
833 
834     // BEGIN Android-removed: Use ICU.
835     // Removed unused helper function that was only used from (unused on Android) code
836     // in format(long, StringBuffer, FieldDelegate).
837     /*
838     /**
839      * Format a long to produce a string.
840      * @param number    The long to format
841      * @param result    where the text is to be appended
842      * @param delegate notified of locations of sub fields
843      * @return The formatted number string
844      * @exception        ArithmeticException if rounding is needed with rounding
845      *                   mode being set to RoundingMode.UNNECESSARY
846      * @see java.text.FieldPosition
847      *
848     private StringBuffer format(long number, StringBuffer result,
849                                FieldDelegate delegate) {
850         boolean isNegative = (number < 0);
851         if (isNegative) {
852             number = -number;
853         }
854 
855         // In general, long values always represent real finite numbers, so
856         // we don't have to check for +/- Infinity or NaN.  However, there
857         // is one case we have to be careful of:  The multiplier can push
858         // a number near MIN_VALUE or MAX_VALUE outside the legal range.  We
859         // check for this before multiplying, and if it happens we use
860         // BigInteger instead.
861         boolean useBigInteger = false;
862         if (number < 0) { // This can only happen if number == Long.MIN_VALUE.
863             if (multiplier != 0) {
864                 useBigInteger = true;
865             }
866         } else if (multiplier != 1 && multiplier != 0) {
867             long cutoff = Long.MAX_VALUE / multiplier;
868             if (cutoff < 0) {
869                 cutoff = -cutoff;
870             }
871             useBigInteger = (number > cutoff);
872         }
873 
874         if (useBigInteger) {
875             if (isNegative) {
876                 number = -number;
877             }
878             BigInteger bigIntegerValue = BigInteger.valueOf(number);
879             return format(bigIntegerValue, result, delegate, true);
880         }
881 
882         number *= multiplier;
883         if (number == 0) {
884             isNegative = false;
885         } else {
886             if (multiplier < 0) {
887                 number = -number;
888                 isNegative = !isNegative;
889             }
890         }
891 
892         synchronized(digitList) {
893             int maxIntDigits = super.getMaximumIntegerDigits();
894             int minIntDigits = super.getMinimumIntegerDigits();
895             int maxFraDigits = super.getMaximumFractionDigits();
896             int minFraDigits = super.getMinimumFractionDigits();
897 
898             digitList.set(isNegative, number,
899                      useExponentialNotation ? maxIntDigits + maxFraDigits : 0);
900 
901             return subformat(result, delegate, isNegative, true,
902                        maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
903         }
904     }
905     */
906     // END Android-removed: Use ICU.
907 
908     /**
909      * Formats a BigDecimal to produce a string.
910      * @param number    The BigDecimal to format
911      * @param result    where the text is to be appended
912      * @param fieldPosition    keeps track on the position of the field within
913      *                         the returned string. For example, for formatting
914      *                         a number {@code 1234567.89} in {@code Locale.US}
915      *                         locale, if the given {@code fieldPosition} is
916      *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
917      *                         and end index of {@code fieldPosition} will be set
918      *                         to 0 and 9, respectively for the output string
919      *                         {@code 1,234,567.89}.
920      * @return The formatted number string
921      * @exception        ArithmeticException if rounding is needed with rounding
922      *                   mode being set to RoundingMode.UNNECESSARY
923      * @see java.text.FieldPosition
924      */
format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition)925     private StringBuffer format(BigDecimal number, StringBuffer result,
926                                 FieldPosition fieldPosition) {
927         // BEGIN Android-changed: Use ICU.
928         /*
929         fieldPosition.setBeginIndex(0);
930         fieldPosition.setEndIndex(0);
931         return format(number, result, fieldPosition.getFieldDelegate());
932         */
933         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
934         icuDecimalFormat.format(number, result, icuFieldPosition);
935         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
936         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
937         return result;
938         // END Android-changed: Use ICU.
939     }
940 
941     // BEGIN Android-removed: Use ICU.
942     // Removed unused helper function that was only used from (unused on Android) code
943     // in format(BigDecimal, StringBuffer, FieldDelegate).
944     /*
945     /**
946      * Formats a BigDecimal to produce a string.
947      * @param number    The BigDecimal to format
948      * @param result    where the text is to be appended
949      * @param delegate notified of locations of sub fields
950      * @exception        ArithmeticException if rounding is needed with rounding
951      *                   mode being set to RoundingMode.UNNECESSARY
952      * @return The formatted number string
953      *
954     private StringBuffer format(BigDecimal number, StringBuffer result,
955                                 FieldDelegate delegate) {
956         if (multiplier != 1) {
957             number = number.multiply(getBigDecimalMultiplier());
958         }
959         boolean isNegative = number.signum() == -1;
960         if (isNegative) {
961             number = number.negate();
962         }
963 
964         synchronized(digitList) {
965             int maxIntDigits = getMaximumIntegerDigits();
966             int minIntDigits = getMinimumIntegerDigits();
967             int maxFraDigits = getMaximumFractionDigits();
968             int minFraDigits = getMinimumFractionDigits();
969             int maximumDigits = maxIntDigits + maxFraDigits;
970 
971             digitList.set(isNegative, number, useExponentialNotation ?
972                 ((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) :
973                 maxFraDigits, !useExponentialNotation);
974 
975             return subformat(result, delegate, isNegative, false,
976                 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
977         }
978     }
979     */
980     // END Android-removed: Use ICU.
981 
982     /**
983      * Format a BigInteger to produce a string.
984      * @param number    The BigInteger to format
985      * @param result    where the text is to be appended
986      * @param fieldPosition    keeps track on the position of the field within
987      *                         the returned string. For example, for formatting
988      *                         a number {@code 123456789} in {@code Locale.US}
989      *                         locale, if the given {@code fieldPosition} is
990      *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
991      *                         and end index of {@code fieldPosition} will be set
992      *                         to 0 and 11, respectively for the output string
993      *                         {@code 123,456,789}.
994      * @return The formatted number string
995      * @exception        ArithmeticException if rounding is needed with rounding
996      *                   mode being set to RoundingMode.UNNECESSARY
997      * @see java.text.FieldPosition
998      */
format(BigInteger number, StringBuffer result, FieldPosition fieldPosition)999     private StringBuffer format(BigInteger number, StringBuffer result,
1000                                FieldPosition fieldPosition) {
1001         // BEGIN Android-changed: Use ICU.
1002         /*
1003         fieldPosition.setBeginIndex(0);
1004         fieldPosition.setEndIndex(0);
1005 
1006         return format(number, result, fieldPosition.getFieldDelegate(), false);
1007         */
1008         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
1009         icuDecimalFormat.format(number, result, icuFieldPosition);
1010         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
1011         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
1012         return result;
1013         // END Android-changed: Use ICU.
1014     }
1015 
1016     // BEGIN Android-removed: Use ICU.
1017     // Removed unused helper function that was only used from (unused on Android) code
1018     // in format(BigInteger, StringBuffer, FieldDelegate).
1019     /*
1020     /**
1021      * Format a BigInteger to produce a string.
1022      * @param number    The BigInteger to format
1023      * @param result    where the text is to be appended
1024      * @param delegate notified of locations of sub fields
1025      * @return The formatted number string
1026      * @exception        ArithmeticException if rounding is needed with rounding
1027      *                   mode being set to RoundingMode.UNNECESSARY
1028      * @see java.text.FieldPosition
1029      *
1030     private StringBuffer format(BigInteger number, StringBuffer result,
1031                                FieldDelegate delegate, boolean formatLong) {
1032         if (multiplier != 1) {
1033             number = number.multiply(getBigIntegerMultiplier());
1034         }
1035         boolean isNegative = number.signum() == -1;
1036         if (isNegative) {
1037             number = number.negate();
1038         }
1039 
1040         synchronized(digitList) {
1041             int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits;
1042             if (formatLong) {
1043                 maxIntDigits = super.getMaximumIntegerDigits();
1044                 minIntDigits = super.getMinimumIntegerDigits();
1045                 maxFraDigits = super.getMaximumFractionDigits();
1046                 minFraDigits = super.getMinimumFractionDigits();
1047                 maximumDigits = maxIntDigits + maxFraDigits;
1048             } else {
1049                 maxIntDigits = getMaximumIntegerDigits();
1050                 minIntDigits = getMinimumIntegerDigits();
1051                 maxFraDigits = getMaximumFractionDigits();
1052                 minFraDigits = getMinimumFractionDigits();
1053                 maximumDigits = maxIntDigits + maxFraDigits;
1054                 if (maximumDigits < 0) {
1055                     maximumDigits = Integer.MAX_VALUE;
1056                 }
1057             }
1058 
1059             digitList.set(isNegative, number,
1060                           useExponentialNotation ? maximumDigits : 0);
1061 
1062             return subformat(result, delegate, isNegative, true,
1063                 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
1064         }
1065     }
1066     */
1067     // END Android-removed: Use ICU.
1068 
1069     /**
1070      * Formats an Object producing an <code>AttributedCharacterIterator</code>.
1071      * You can use the returned <code>AttributedCharacterIterator</code>
1072      * to build the resulting String, as well as to determine information
1073      * about the resulting String.
1074      * <p>
1075      * Each attribute key of the AttributedCharacterIterator will be of type
1076      * <code>NumberFormat.Field</code>, with the attribute value being the
1077      * same as the attribute key.
1078      *
1079      * @exception NullPointerException if obj is null.
1080      * @exception IllegalArgumentException when the Format cannot format the
1081      *            given object.
1082      * @exception        ArithmeticException if rounding is needed with rounding
1083      *                   mode being set to RoundingMode.UNNECESSARY
1084      * @param obj The object to format
1085      * @return AttributedCharacterIterator describing the formatted value.
1086      * @since 1.4
1087      */
1088     @Override
formatToCharacterIterator(Object obj)1089     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
1090         // BEGIN Android-changed: Use ICU.
1091         /*
1092         CharacterIteratorFieldDelegate delegate =
1093                          new CharacterIteratorFieldDelegate();
1094         StringBuffer sb = new StringBuffer();
1095 
1096         if (obj instanceof Double || obj instanceof Float) {
1097             format(((Number)obj).doubleValue(), sb, delegate);
1098         } else if (obj instanceof Long || obj instanceof Integer ||
1099                    obj instanceof Short || obj instanceof Byte ||
1100                    obj instanceof AtomicInteger || obj instanceof AtomicLong) {
1101             format(((Number)obj).longValue(), sb, delegate);
1102         } else if (obj instanceof BigDecimal) {
1103             format((BigDecimal)obj, sb, delegate);
1104         } else if (obj instanceof BigInteger) {
1105             format((BigInteger)obj, sb, delegate, false);
1106         } else if (obj == null) {
1107             throw new NullPointerException(
1108                 "formatToCharacterIterator must be passed non-null object");
1109         } else {
1110             throw new IllegalArgumentException(
1111                 "Cannot format given Object as a Number");
1112         }
1113         return delegate.getIterator(sb.toString());
1114         */
1115         if (obj == null) {
1116             throw new NullPointerException("object == null");
1117         }
1118         // Note: formatToCharacterIterator cannot be used directly because it returns attributes
1119         // in terms of its own class: icu.text.NumberFormat instead of java.text.NumberFormat.
1120         // http://bugs.icu-project.org/trac/ticket/11931 Proposes to use the NumberFormat constants.
1121 
1122         AttributedCharacterIterator original = icuDecimalFormat.formatToCharacterIterator(obj);
1123 
1124         // Extract the text out of the ICU iterator.
1125         StringBuilder textBuilder = new StringBuilder(
1126                 original.getEndIndex() - original.getBeginIndex());
1127 
1128         for (int i = original.getBeginIndex(); i < original.getEndIndex(); i++) {
1129             textBuilder.append(original.current());
1130             original.next();
1131         }
1132 
1133         AttributedString result = new AttributedString(textBuilder.toString());
1134 
1135         for (int i = original.getBeginIndex(); i < original.getEndIndex(); i++) {
1136             original.setIndex(i);
1137 
1138             for (AttributedCharacterIterator.Attribute attribute
1139                     : original.getAttributes().keySet()) {
1140                     int start = original.getRunStart();
1141                     int end = original.getRunLimit();
1142                     Field javaAttr = toJavaFieldAttribute(attribute);
1143                     result.addAttribute(javaAttr, javaAttr, start, end);
1144             }
1145         }
1146 
1147         return result.getIterator();
1148         // END Android-changed: Use ICU.
1149     }
1150 
1151     // BEGIN Android-removed: "fast-path formatting logic for double", subformat(), append().
1152     /*
1153     // ==== Begin fast-path formating logic for double =========================
1154 
1155     /* Fast-path formatting will be used for format(double ...) methods iff a
1156      * number of conditions are met (see checkAndSetFastPathStatus()):
1157      * - Only if instance properties meet the right predefined conditions.
1158      * - The abs value of the double to format is <= Integer.MAX_VALUE.
1159      *
1160      * The basic approach is to split the binary to decimal conversion of a
1161      * double value into two phases:
1162      * * The conversion of the integer portion of the double.
1163      * * The conversion of the fractional portion of the double
1164      *   (limited to two or three digits).
1165      *
1166      * The isolation and conversion of the integer portion of the double is
1167      * straightforward. The conversion of the fraction is more subtle and relies
1168      * on some rounding properties of double to the decimal precisions in
1169      * question.  Using the terminology of BigDecimal, this fast-path algorithm
1170      * is applied when a double value has a magnitude less than Integer.MAX_VALUE
1171      * and rounding is to nearest even and the destination format has two or
1172      * three digits of *scale* (digits after the decimal point).
1173      *
1174      * Under a rounding to nearest even policy, the returned result is a digit
1175      * string of a number in the (in this case decimal) destination format
1176      * closest to the exact numerical value of the (in this case binary) input
1177      * value.  If two destination format numbers are equally distant, the one
1178      * with the last digit even is returned.  To compute such a correctly rounded
1179      * value, some information about digits beyond the smallest returned digit
1180      * position needs to be consulted.
1181      *
1182      * In general, a guard digit, a round digit, and a sticky *bit* are needed
1183      * beyond the returned digit position.  If the discarded portion of the input
1184      * is sufficiently large, the returned digit string is incremented.  In round
1185      * to nearest even, this threshold to increment occurs near the half-way
1186      * point between digits.  The sticky bit records if there are any remaining
1187      * trailing digits of the exact input value in the new format; the sticky bit
1188      * is consulted only in close to half-way rounding cases.
1189      *
1190      * Given the computation of the digit and bit values, rounding is then
1191      * reduced to a table lookup problem.  For decimal, the even/odd cases look
1192      * like this:
1193      *
1194      * Last   Round   Sticky
1195      * 6      5       0      => 6   // exactly halfway, return even digit.
1196      * 6      5       1      => 7   // a little bit more than halfway, round up.
1197      * 7      5       0      => 8   // exactly halfway, round up to even.
1198      * 7      5       1      => 8   // a little bit more than halfway, round up.
1199      * With analogous entries for other even and odd last-returned digits.
1200      *
1201      * However, decimal negative powers of 5 smaller than 0.5 are *not* exactly
1202      * representable as binary fraction.  In particular, 0.005 (the round limit
1203      * for a two-digit scale) and 0.0005 (the round limit for a three-digit
1204      * scale) are not representable. Therefore, for input values near these cases
1205      * the sticky bit is known to be set which reduces the rounding logic to:
1206      *
1207      * Last   Round   Sticky
1208      * 6      5       1      => 7   // a little bit more than halfway, round up.
1209      * 7      5       1      => 8   // a little bit more than halfway, round up.
1210      *
1211      * In other words, if the round digit is 5, the sticky bit is known to be
1212      * set.  If the round digit is something other than 5, the sticky bit is not
1213      * relevant.  Therefore, some of the logic about whether or not to increment
1214      * the destination *decimal* value can occur based on tests of *binary*
1215      * computations of the binary input number.
1216      *
1217 
1218     /**
1219      * Check validity of using fast-path for this instance. If fast-path is valid
1220      * for this instance, sets fast-path state as true and initializes fast-path
1221      * utility fields as needed.
1222      *
1223      * This method is supposed to be called rarely, otherwise that will break the
1224      * fast-path performance. That means avoiding frequent changes of the
1225      * properties of the instance, since for most properties, each time a change
1226      * happens, a call to this method is needed at the next format call.
1227      *
1228      * FAST-PATH RULES:
1229      *  Similar to the default DecimalFormat instantiation case.
1230      *  More precisely:
1231      *  - HALF_EVEN rounding mode,
1232      *  - isGroupingUsed() is true,
1233      *  - groupingSize of 3,
1234      *  - multiplier is 1,
1235      *  - Decimal separator not mandatory,
1236      *  - No use of exponential notation,
1237      *  - minimumIntegerDigits is exactly 1 and maximumIntegerDigits at least 10
1238      *  - For number of fractional digits, the exact values found in the default case:
1239      *     Currency : min = max = 2.
1240      *     Decimal  : min = 0. max = 3.
1241      *
1242      *
1243      *
1244     private boolean checkAndSetFastPathStatus() {
1245 
1246         boolean fastPathWasOn = isFastPath;
1247 
1248         if ((roundingMode == RoundingMode.HALF_EVEN) &&
1249             (isGroupingUsed()) &&
1250             (groupingSize == 3) &&
1251             (multiplier == 1) &&
1252             (!decimalSeparatorAlwaysShown) &&
1253             (!useExponentialNotation)) {
1254 
1255             // The fast-path algorithm is semi-hardcoded against
1256             //  minimumIntegerDigits and maximumIntegerDigits.
1257             isFastPath = ((minimumIntegerDigits == 1) &&
1258                           (maximumIntegerDigits >= 10));
1259 
1260             // The fast-path algorithm is hardcoded against
1261             //  minimumFractionDigits and maximumFractionDigits.
1262             if (isFastPath) {
1263                 if (isCurrencyFormat) {
1264                     if ((minimumFractionDigits != 2) ||
1265                         (maximumFractionDigits != 2))
1266                         isFastPath = false;
1267                 } else if ((minimumFractionDigits != 0) ||
1268                            (maximumFractionDigits != 3))
1269                     isFastPath = false;
1270             }
1271         } else
1272             isFastPath = false;
1273 
1274         resetFastPathData(fastPathWasOn);
1275         fastPathCheckNeeded = false;
1276 
1277         /*
1278          * Returns true after successfully checking the fast path condition and
1279          * setting the fast path data. The return value is used by the
1280          * fastFormat() method to decide whether to call the resetFastPathData
1281          * method to reinitialize fast path data or is it already initialized
1282          * in this method.
1283          *
1284         return true;
1285     }
1286 
1287     private void resetFastPathData(boolean fastPathWasOn) {
1288         // Since some instance properties may have changed while still falling
1289         // in the fast-path case, we need to reinitialize fastPathData anyway.
1290         if (isFastPath) {
1291             // We need to instantiate fastPathData if not already done.
1292             if (fastPathData == null) {
1293                 fastPathData = new FastPathData();
1294             }
1295 
1296             // Sets up the locale specific constants used when formatting.
1297             // '0' is our default representation of zero.
1298             fastPathData.zeroDelta = symbols.getZeroDigit() - '0';
1299             fastPathData.groupingChar = symbols.getGroupingSeparator();
1300 
1301             // Sets up fractional constants related to currency/decimal pattern.
1302             fastPathData.fractionalMaxIntBound = (isCurrencyFormat)
1303                     ? 99 : 999;
1304             fastPathData.fractionalScaleFactor = (isCurrencyFormat)
1305                     ? 100.0d : 1000.0d;
1306 
1307             // Records the need for adding prefix or suffix
1308             fastPathData.positiveAffixesRequired
1309                     = !positivePrefix.isEmpty() || !positiveSuffix.isEmpty();
1310             fastPathData.negativeAffixesRequired
1311                     = !negativePrefix.isEmpty() || !negativeSuffix.isEmpty();
1312 
1313             // Creates a cached char container for result, with max possible size.
1314             int maxNbIntegralDigits = 10;
1315             int maxNbGroups = 3;
1316             int containerSize
1317                     = Math.max(positivePrefix.length(), negativePrefix.length())
1318                     + maxNbIntegralDigits + maxNbGroups + 1
1319                     + maximumFractionDigits
1320                     + Math.max(positiveSuffix.length(), negativeSuffix.length());
1321 
1322             fastPathData.fastPathContainer = new char[containerSize];
1323 
1324             // Sets up prefix and suffix char arrays constants.
1325             fastPathData.charsPositiveSuffix = positiveSuffix.toCharArray();
1326             fastPathData.charsNegativeSuffix = negativeSuffix.toCharArray();
1327             fastPathData.charsPositivePrefix = positivePrefix.toCharArray();
1328             fastPathData.charsNegativePrefix = negativePrefix.toCharArray();
1329 
1330             // Sets up fixed index positions for integral and fractional digits.
1331             // Sets up decimal point in cached result container.
1332             int longestPrefixLength
1333                     = Math.max(positivePrefix.length(),
1334                             negativePrefix.length());
1335             int decimalPointIndex
1336                     = maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
1337 
1338             fastPathData.integralLastIndex = decimalPointIndex - 1;
1339             fastPathData.fractionalFirstIndex = decimalPointIndex + 1;
1340             fastPathData.fastPathContainer[decimalPointIndex]
1341                     = isCurrencyFormat
1342                             ? symbols.getMonetaryDecimalSeparator()
1343                             : symbols.getDecimalSeparator();
1344 
1345         } else if (fastPathWasOn) {
1346             // Previous state was fast-path and is no more.
1347             // Resets cached array constants.
1348             fastPathData.fastPathContainer = null;
1349             fastPathData.charsPositiveSuffix = null;
1350             fastPathData.charsNegativeSuffix = null;
1351             fastPathData.charsPositivePrefix = null;
1352             fastPathData.charsNegativePrefix = null;
1353         }
1354     }
1355 
1356     /**
1357      * Returns true if rounding-up must be done on {@code scaledFractionalPartAsInt},
1358      * false otherwise.
1359      *
1360      * This is a utility method that takes correct half-even rounding decision on
1361      * passed fractional value at the scaled decimal point (2 digits for currency
1362      * case and 3 for decimal case), when the approximated fractional part after
1363      * scaled decimal point is exactly 0.5d.  This is done by means of exact
1364      * calculations on the {@code fractionalPart} floating-point value.
1365      *
1366      * This method is supposed to be called by private {@code fastDoubleFormat}
1367      * method only.
1368      *
1369      * The algorithms used for the exact calculations are :
1370      *
1371      * The <b><i>FastTwoSum</i></b> algorithm, from T.J.Dekker, described in the
1372      * papers  "<i>A  Floating-Point   Technique  for  Extending  the  Available
1373      * Precision</i>"  by Dekker, and  in "<i>Adaptive  Precision Floating-Point
1374      * Arithmetic and Fast Robust Geometric Predicates</i>" from J.Shewchuk.
1375      *
1376      * A modified version of <b><i>Sum2S</i></b> cascaded summation described in
1377      * "<i>Accurate Sum and Dot Product</i>" from Takeshi Ogita and All.  As
1378      * Ogita says in this paper this is an equivalent of the Kahan-Babuska's
1379      * summation algorithm because we order the terms by magnitude before summing
1380      * them. For this reason we can use the <i>FastTwoSum</i> algorithm rather
1381      * than the more expensive Knuth's <i>TwoSum</i>.
1382      *
1383      * We do this to avoid a more expensive exact "<i>TwoProduct</i>" algorithm,
1384      * like those described in Shewchuk's paper above. See comments in the code
1385      * below.
1386      *
1387      * @param  fractionalPart The  fractional value  on which  we  take rounding
1388      * decision.
1389      * @param scaledFractionalPartAsInt The integral part of the scaled
1390      * fractional value.
1391      *
1392      * @return the decision that must be taken regarding half-even rounding.
1393      *
1394     private boolean exactRoundUp(double fractionalPart,
1395                                  int scaledFractionalPartAsInt) {
1396 
1397         /* exactRoundUp() method is called by fastDoubleFormat() only.
1398          * The precondition expected to be verified by the passed parameters is :
1399          * scaledFractionalPartAsInt ==
1400          *     (int) (fractionalPart * fastPathData.fractionalScaleFactor).
1401          * This is ensured by fastDoubleFormat() code.
1402          *
1403 
1404         /* We first calculate roundoff error made by fastDoubleFormat() on
1405          * the scaled fractional part. We do this with exact calculation on the
1406          * passed fractionalPart. Rounding decision will then be taken from roundoff.
1407          *
1408 
1409         /* ---- TwoProduct(fractionalPart, scale factor (i.e. 1000.0d or 100.0d)).
1410          *
1411          * The below is an optimized exact "TwoProduct" calculation of passed
1412          * fractional part with scale factor, using Ogita's Sum2S cascaded
1413          * summation adapted as Kahan-Babuska equivalent by using FastTwoSum
1414          * (much faster) rather than Knuth's TwoSum.
1415          *
1416          * We can do this because we order the summation from smallest to
1417          * greatest, so that FastTwoSum can be used without any additional error.
1418          *
1419          * The "TwoProduct" exact calculation needs 17 flops. We replace this by
1420          * a cascaded summation of FastTwoSum calculations, each involving an
1421          * exact multiply by a power of 2.
1422          *
1423          * Doing so saves overall 4 multiplications and 1 addition compared to
1424          * using traditional "TwoProduct".
1425          *
1426          * The scale factor is either 100 (currency case) or 1000 (decimal case).
1427          * - when 1000, we replace it by (1024 - 16 - 8) = 1000.
1428          * - when 100,  we replace it by (128  - 32 + 4) =  100.
1429          * Every multiplication by a power of 2 (1024, 128, 32, 16, 8, 4) is exact.
1430          *
1431          *
1432         double approxMax;    // Will always be positive.
1433         double approxMedium; // Will always be negative.
1434         double approxMin;
1435 
1436         double fastTwoSumApproximation = 0.0d;
1437         double fastTwoSumRoundOff = 0.0d;
1438         double bVirtual = 0.0d;
1439 
1440         if (isCurrencyFormat) {
1441             // Scale is 100 = 128 - 32 + 4.
1442             // Multiply by 2**n is a shift. No roundoff. No error.
1443             approxMax    = fractionalPart * 128.00d;
1444             approxMedium = - (fractionalPart * 32.00d);
1445             approxMin    = fractionalPart * 4.00d;
1446         } else {
1447             // Scale is 1000 = 1024 - 16 - 8.
1448             // Multiply by 2**n is a shift. No roundoff. No error.
1449             approxMax    = fractionalPart * 1024.00d;
1450             approxMedium = - (fractionalPart * 16.00d);
1451             approxMin    = - (fractionalPart * 8.00d);
1452         }
1453 
1454         // Shewchuk/Dekker's FastTwoSum(approxMedium, approxMin).
1455         assert(-approxMedium >= Math.abs(approxMin));
1456         fastTwoSumApproximation = approxMedium + approxMin;
1457         bVirtual = fastTwoSumApproximation - approxMedium;
1458         fastTwoSumRoundOff = approxMin - bVirtual;
1459         double approxS1 = fastTwoSumApproximation;
1460         double roundoffS1 = fastTwoSumRoundOff;
1461 
1462         // Shewchuk/Dekker's FastTwoSum(approxMax, approxS1);
1463         assert(approxMax >= Math.abs(approxS1));
1464         fastTwoSumApproximation = approxMax + approxS1;
1465         bVirtual = fastTwoSumApproximation - approxMax;
1466         fastTwoSumRoundOff = approxS1 - bVirtual;
1467         double roundoff1000 = fastTwoSumRoundOff;
1468         double approx1000 = fastTwoSumApproximation;
1469         double roundoffTotal = roundoffS1 + roundoff1000;
1470 
1471         // Shewchuk/Dekker's FastTwoSum(approx1000, roundoffTotal);
1472         assert(approx1000 >= Math.abs(roundoffTotal));
1473         fastTwoSumApproximation = approx1000 + roundoffTotal;
1474         bVirtual = fastTwoSumApproximation - approx1000;
1475 
1476         // Now we have got the roundoff for the scaled fractional
1477         double scaledFractionalRoundoff = roundoffTotal - bVirtual;
1478 
1479         // ---- TwoProduct(fractionalPart, scale (i.e. 1000.0d or 100.0d)) end.
1480 
1481         /* ---- Taking the rounding decision
1482          *
1483          * We take rounding decision based on roundoff and half-even rounding
1484          * rule.
1485          *
1486          * The above TwoProduct gives us the exact roundoff on the approximated
1487          * scaled fractional, and we know that this approximation is exactly
1488          * 0.5d, since that has already been tested by the caller
1489          * (fastDoubleFormat).
1490          *
1491          * Decision comes first from the sign of the calculated exact roundoff.
1492          * - Since being exact roundoff, it cannot be positive with a scaled
1493          *   fractional less than 0.5d, as well as negative with a scaled
1494          *   fractional greater than 0.5d. That leaves us with following 3 cases.
1495          * - positive, thus scaled fractional == 0.500....0fff ==> round-up.
1496          * - negative, thus scaled fractional == 0.499....9fff ==> don't round-up.
1497          * - is zero,  thus scaled fractioanl == 0.5 ==> half-even rounding applies :
1498          *    we round-up only if the integral part of the scaled fractional is odd.
1499          *
1500          *
1501         if (scaledFractionalRoundoff > 0.0) {
1502             return true;
1503         } else if (scaledFractionalRoundoff < 0.0) {
1504             return false;
1505         } else if ((scaledFractionalPartAsInt & 1) != 0) {
1506             return true;
1507         }
1508 
1509         return false;
1510 
1511         // ---- Taking the rounding decision end
1512     }
1513 
1514     /**
1515      * Collects integral digits from passed {@code number}, while setting
1516      * grouping chars as needed. Updates {@code firstUsedIndex} accordingly.
1517      *
1518      * Loops downward starting from {@code backwardIndex} position (inclusive).
1519      *
1520      * @param number  The int value from which we collect digits.
1521      * @param digitsBuffer The char array container where digits and grouping chars
1522      *  are stored.
1523      * @param backwardIndex the position from which we start storing digits in
1524      *  digitsBuffer.
1525      *
1526      *
1527     private void collectIntegralDigits(int number,
1528                                        char[] digitsBuffer,
1529                                        int backwardIndex) {
1530         int index = backwardIndex;
1531         int q;
1532         int r;
1533         while (number > 999) {
1534             // Generates 3 digits per iteration.
1535             q = number / 1000;
1536             r = number - (q << 10) + (q << 4) + (q << 3); // -1024 +16 +8 = 1000.
1537             number = q;
1538 
1539             digitsBuffer[index--] = DigitArrays.DigitOnes1000[r];
1540             digitsBuffer[index--] = DigitArrays.DigitTens1000[r];
1541             digitsBuffer[index--] = DigitArrays.DigitHundreds1000[r];
1542             digitsBuffer[index--] = fastPathData.groupingChar;
1543         }
1544 
1545         // Collects last 3 or less digits.
1546         digitsBuffer[index] = DigitArrays.DigitOnes1000[number];
1547         if (number > 9) {
1548             digitsBuffer[--index]  = DigitArrays.DigitTens1000[number];
1549             if (number > 99)
1550                 digitsBuffer[--index]   = DigitArrays.DigitHundreds1000[number];
1551         }
1552 
1553         fastPathData.firstUsedIndex = index;
1554     }
1555 
1556     /**
1557      * Collects the 2 (currency) or 3 (decimal) fractional digits from passed
1558      * {@code number}, starting at {@code startIndex} position
1559      * inclusive.  There is no punctuation to set here (no grouping chars).
1560      * Updates {@code fastPathData.lastFreeIndex} accordingly.
1561      *
1562      *
1563      * @param number  The int value from which we collect digits.
1564      * @param digitsBuffer The char array container where digits are stored.
1565      * @param startIndex the position from which we start storing digits in
1566      *  digitsBuffer.
1567      *
1568      *
1569     private void collectFractionalDigits(int number,
1570                                          char[] digitsBuffer,
1571                                          int startIndex) {
1572         int index = startIndex;
1573 
1574         char digitOnes = DigitArrays.DigitOnes1000[number];
1575         char digitTens = DigitArrays.DigitTens1000[number];
1576 
1577         if (isCurrencyFormat) {
1578             // Currency case. Always collects fractional digits.
1579             digitsBuffer[index++] = digitTens;
1580             digitsBuffer[index++] = digitOnes;
1581         } else if (number != 0) {
1582             // Decimal case. Hundreds will always be collected
1583             digitsBuffer[index++] = DigitArrays.DigitHundreds1000[number];
1584 
1585             // Ending zeros won't be collected.
1586             if (digitOnes != '0') {
1587                 digitsBuffer[index++] = digitTens;
1588                 digitsBuffer[index++] = digitOnes;
1589             } else if (digitTens != '0')
1590                 digitsBuffer[index++] = digitTens;
1591 
1592         } else
1593             // This is decimal pattern and fractional part is zero.
1594             // We must remove decimal point from result.
1595             index--;
1596 
1597         fastPathData.lastFreeIndex = index;
1598     }
1599 
1600     /**
1601      * Internal utility.
1602      * Adds the passed {@code prefix} and {@code suffix} to {@code container}.
1603      *
1604      * @param container  Char array container which to prepend/append the
1605      *  prefix/suffix.
1606      * @param prefix     Char sequence to prepend as a prefix.
1607      * @param suffix     Char sequence to append as a suffix.
1608      *
1609      *
1610     //    private void addAffixes(boolean isNegative, char[] container) {
1611     private void addAffixes(char[] container, char[] prefix, char[] suffix) {
1612 
1613         // We add affixes only if needed (affix length > 0).
1614         int pl = prefix.length;
1615         int sl = suffix.length;
1616         if (pl != 0) prependPrefix(prefix, pl, container);
1617         if (sl != 0) appendSuffix(suffix, sl, container);
1618 
1619     }
1620 
1621     /**
1622      * Prepends the passed {@code prefix} chars to given result
1623      * {@code container}.  Updates {@code fastPathData.firstUsedIndex}
1624      * accordingly.
1625      *
1626      * @param prefix The prefix characters to prepend to result.
1627      * @param len The number of chars to prepend.
1628      * @param container Char array container which to prepend the prefix
1629      *
1630     private void prependPrefix(char[] prefix,
1631                                int len,
1632                                char[] container) {
1633 
1634         fastPathData.firstUsedIndex -= len;
1635         int startIndex = fastPathData.firstUsedIndex;
1636 
1637         // If prefix to prepend is only 1 char long, just assigns this char.
1638         // If prefix is less or equal 4, we use a dedicated algorithm that
1639         //  has shown to run faster than System.arraycopy.
1640         // If more than 4, we use System.arraycopy.
1641         if (len == 1)
1642             container[startIndex] = prefix[0];
1643         else if (len <= 4) {
1644             int dstLower = startIndex;
1645             int dstUpper = dstLower + len - 1;
1646             int srcUpper = len - 1;
1647             container[dstLower] = prefix[0];
1648             container[dstUpper] = prefix[srcUpper];
1649 
1650             if (len > 2)
1651                 container[++dstLower] = prefix[1];
1652             if (len == 4)
1653                 container[--dstUpper] = prefix[2];
1654         } else
1655             System.arraycopy(prefix, 0, container, startIndex, len);
1656     }
1657 
1658     /**
1659      * Appends the passed {@code suffix} chars to given result
1660      * {@code container}.  Updates {@code fastPathData.lastFreeIndex}
1661      * accordingly.
1662      *
1663      * @param suffix The suffix characters to append to result.
1664      * @param len The number of chars to append.
1665      * @param container Char array container which to append the suffix
1666      *
1667     private void appendSuffix(char[] suffix,
1668                               int len,
1669                               char[] container) {
1670 
1671         int startIndex = fastPathData.lastFreeIndex;
1672 
1673         // If suffix to append is only 1 char long, just assigns this char.
1674         // If suffix is less or equal 4, we use a dedicated algorithm that
1675         //  has shown to run faster than System.arraycopy.
1676         // If more than 4, we use System.arraycopy.
1677         if (len == 1)
1678             container[startIndex] = suffix[0];
1679         else if (len <= 4) {
1680             int dstLower = startIndex;
1681             int dstUpper = dstLower + len - 1;
1682             int srcUpper = len - 1;
1683             container[dstLower] = suffix[0];
1684             container[dstUpper] = suffix[srcUpper];
1685 
1686             if (len > 2)
1687                 container[++dstLower] = suffix[1];
1688             if (len == 4)
1689                 container[--dstUpper] = suffix[2];
1690         } else
1691             System.arraycopy(suffix, 0, container, startIndex, len);
1692 
1693         fastPathData.lastFreeIndex += len;
1694     }
1695 
1696     /**
1697      * Converts digit chars from {@code digitsBuffer} to current locale.
1698      *
1699      * Must be called before adding affixes since we refer to
1700      * {@code fastPathData.firstUsedIndex} and {@code fastPathData.lastFreeIndex},
1701      * and do not support affixes (for speed reason).
1702      *
1703      * We loop backward starting from last used index in {@code fastPathData}.
1704      *
1705      * @param digitsBuffer The char array container where the digits are stored.
1706      *
1707     private void localizeDigits(char[] digitsBuffer) {
1708 
1709         // We will localize only the digits, using the groupingSize,
1710         // and taking into account fractional part.
1711 
1712         // First take into account fractional part.
1713         int digitsCounter =
1714             fastPathData.lastFreeIndex - fastPathData.fractionalFirstIndex;
1715 
1716         // The case when there is no fractional digits.
1717         if (digitsCounter < 0)
1718             digitsCounter = groupingSize;
1719 
1720         // Only the digits remains to localize.
1721         for (int cursor = fastPathData.lastFreeIndex - 1;
1722              cursor >= fastPathData.firstUsedIndex;
1723              cursor--) {
1724             if (digitsCounter != 0) {
1725                 // This is a digit char, we must localize it.
1726                 digitsBuffer[cursor] += fastPathData.zeroDelta;
1727                 digitsCounter--;
1728             } else {
1729                 // Decimal separator or grouping char. Reinit counter only.
1730                 digitsCounter = groupingSize;
1731             }
1732         }
1733     }
1734 
1735     /**
1736      * This is the main entry point for the fast-path format algorithm.
1737      *
1738      * At this point we are sure to be in the expected conditions to run it.
1739      * This algorithm builds the formatted result and puts it in the dedicated
1740      * {@code fastPathData.fastPathContainer}.
1741      *
1742      * @param d the double value to be formatted.
1743      * @param negative Flag precising if {@code d} is negative.
1744      *
1745     private void fastDoubleFormat(double d,
1746                                   boolean negative) {
1747 
1748         char[] container = fastPathData.fastPathContainer;
1749 
1750         /*
1751          * The principle of the algorithm is to :
1752          * - Break the passed double into its integral and fractional parts
1753          *    converted into integers.
1754          * - Then decide if rounding up must be applied or not by following
1755          *    the half-even rounding rule, first using approximated scaled
1756          *    fractional part.
1757          * - For the difficult cases (approximated scaled fractional part
1758          *    being exactly 0.5d), we refine the rounding decision by calling
1759          *    exactRoundUp utility method that both calculates the exact roundoff
1760          *    on the approximation and takes correct rounding decision.
1761          * - We round-up the fractional part if needed, possibly propagating the
1762          *    rounding to integral part if we meet a "all-nine" case for the
1763          *    scaled fractional part.
1764          * - We then collect digits from the resulting integral and fractional
1765          *   parts, also setting the required grouping chars on the fly.
1766          * - Then we localize the collected digits if needed, and
1767          * - Finally prepend/append prefix/suffix if any is needed.
1768          *
1769 
1770         // Exact integral part of d.
1771         int integralPartAsInt = (int) d;
1772 
1773         // Exact fractional part of d (since we subtract it's integral part).
1774         double exactFractionalPart = d - (double) integralPartAsInt;
1775 
1776         // Approximated scaled fractional part of d (due to multiplication).
1777         double scaledFractional =
1778             exactFractionalPart * fastPathData.fractionalScaleFactor;
1779 
1780         // Exact integral part of scaled fractional above.
1781         int fractionalPartAsInt = (int) scaledFractional;
1782 
1783         // Exact fractional part of scaled fractional above.
1784         scaledFractional = scaledFractional - (double) fractionalPartAsInt;
1785 
1786         // Only when scaledFractional is exactly 0.5d do we have to do exact
1787         // calculations and take fine-grained rounding decision, since
1788         // approximated results above may lead to incorrect decision.
1789         // Otherwise comparing against 0.5d (strictly greater or less) is ok.
1790         boolean roundItUp = false;
1791         if (scaledFractional >= 0.5d) {
1792             if (scaledFractional == 0.5d)
1793                 // Rounding need fine-grained decision.
1794                 roundItUp = exactRoundUp(exactFractionalPart, fractionalPartAsInt);
1795             else
1796                 roundItUp = true;
1797 
1798             if (roundItUp) {
1799                 // Rounds up both fractional part (and also integral if needed).
1800                 if (fractionalPartAsInt < fastPathData.fractionalMaxIntBound) {
1801                     fractionalPartAsInt++;
1802                 } else {
1803                     // Propagates rounding to integral part since "all nines" case.
1804                     fractionalPartAsInt = 0;
1805                     integralPartAsInt++;
1806                 }
1807             }
1808         }
1809 
1810         // Collecting digits.
1811         collectFractionalDigits(fractionalPartAsInt, container,
1812                                 fastPathData.fractionalFirstIndex);
1813         collectIntegralDigits(integralPartAsInt, container,
1814                               fastPathData.integralLastIndex);
1815 
1816         // Localizing digits.
1817         if (fastPathData.zeroDelta != 0)
1818             localizeDigits(container);
1819 
1820         // Adding prefix and suffix.
1821         if (negative) {
1822             if (fastPathData.negativeAffixesRequired)
1823                 addAffixes(container,
1824                            fastPathData.charsNegativePrefix,
1825                            fastPathData.charsNegativeSuffix);
1826         } else if (fastPathData.positiveAffixesRequired)
1827             addAffixes(container,
1828                        fastPathData.charsPositivePrefix,
1829                        fastPathData.charsPositiveSuffix);
1830     }
1831 
1832     /**
1833      * A fast-path shortcut of format(double) to be called by NumberFormat, or by
1834      * format(double, ...) public methods.
1835      *
1836      * If instance can be applied fast-path and passed double is not NaN or
1837      * Infinity, is in the integer range, we call {@code fastDoubleFormat}
1838      * after changing {@code d} to its positive value if necessary.
1839      *
1840      * Otherwise returns null by convention since fast-path can't be exercized.
1841      *
1842      * @param d The double value to be formatted
1843      *
1844      * @return the formatted result for {@code d} as a string.
1845      *
1846     String fastFormat(double d) {
1847         boolean isDataSet = false;
1848         // (Re-)Evaluates fast-path status if needed.
1849         if (fastPathCheckNeeded) {
1850             isDataSet = checkAndSetFastPathStatus();
1851         }
1852 
1853         if (!isFastPath )
1854             // DecimalFormat instance is not in a fast-path state.
1855             return null;
1856 
1857         if (!Double.isFinite(d))
1858             // Should not use fast-path for Infinity and NaN.
1859             return null;
1860 
1861         // Extracts and records sign of double value, possibly changing it
1862         // to a positive one, before calling fastDoubleFormat().
1863         boolean negative = false;
1864         if (d < 0.0d) {
1865             negative = true;
1866             d = -d;
1867         } else if (d == 0.0d) {
1868             negative = (Math.copySign(1.0d, d) == -1.0d);
1869             d = +0.0d;
1870         }
1871 
1872         if (d > MAX_INT_AS_DOUBLE)
1873             // Filters out values that are outside expected fast-path range
1874             return null;
1875         else {
1876             if (!isDataSet) {
1877                 /*
1878                  * If the fast path data is not set through
1879                  * checkAndSetFastPathStatus() and fulfil the
1880                  * fast path conditions then reset the data
1881                  * directly through resetFastPathData()
1882                  *
1883                 resetFastPathData(isFastPath);
1884             }
1885             fastDoubleFormat(d, negative);
1886 
1887         }
1888 
1889 
1890         // Returns a new string from updated fastPathContainer.
1891         return new String(fastPathData.fastPathContainer,
1892                           fastPathData.firstUsedIndex,
1893                           fastPathData.lastFreeIndex - fastPathData.firstUsedIndex);
1894 
1895     }
1896 
1897     // ======== End fast-path formating logic for double =========================
1898 
1899     /**
1900      * Complete the formatting of a finite number.  On entry, the digitList must
1901      * be filled in with the correct digits.
1902      *
1903     private StringBuffer subformat(StringBuffer result, FieldDelegate delegate,
1904                                    boolean isNegative, boolean isInteger,
1905                                    int maxIntDigits, int minIntDigits,
1906                                    int maxFraDigits, int minFraDigits) {
1907         // NOTE: This isn't required anymore because DigitList takes care of this.
1908         //
1909         //  // The negative of the exponent represents the number of leading
1910         //  // zeros between the decimal and the first non-zero digit, for
1911         //  // a value < 0.1 (e.g., for 0.00123, -fExponent == 2).  If this
1912         //  // is more than the maximum fraction digits, then we have an underflow
1913         //  // for the printed representation.  We recognize this here and set
1914         //  // the DigitList representation to zero in this situation.
1915         //
1916         //  if (-digitList.decimalAt >= getMaximumFractionDigits())
1917         //  {
1918         //      digitList.count = 0;
1919         //  }
1920 
1921         char zero = symbols.getZeroDigit();
1922         int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
1923         char grouping = symbols.getGroupingSeparator();
1924         char decimal = isCurrencyFormat ?
1925             symbols.getMonetaryDecimalSeparator() :
1926             symbols.getDecimalSeparator();
1927 
1928         /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
1929          * format as zero.  This allows sensible computations and preserves
1930          * relations such as signum(1/x) = signum(x), where x is +Infinity or
1931          * -Infinity.  Prior to this fix, we always formatted zero values as if
1932          * they were positive.  Liu 7/6/98.
1933          *
1934         if (digitList.isZero()) {
1935             digitList.decimalAt = 0; // Normalize
1936         }
1937 
1938         if (isNegative) {
1939             append(result, negativePrefix, delegate,
1940                    getNegativePrefixFieldPositions(), Field.SIGN);
1941         } else {
1942             append(result, positivePrefix, delegate,
1943                    getPositivePrefixFieldPositions(), Field.SIGN);
1944         }
1945 
1946         if (useExponentialNotation) {
1947             int iFieldStart = result.length();
1948             int iFieldEnd = -1;
1949             int fFieldStart = -1;
1950 
1951             // Minimum integer digits are handled in exponential format by
1952             // adjusting the exponent.  For example, 0.01234 with 3 minimum
1953             // integer digits is "123.4E-4".
1954 
1955             // Maximum integer digits are interpreted as indicating the
1956             // repeating range.  This is useful for engineering notation, in
1957             // which the exponent is restricted to a multiple of 3.  For
1958             // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
1959             // If maximum integer digits are > 1 and are larger than
1960             // minimum integer digits, then minimum integer digits are
1961             // ignored.
1962             int exponent = digitList.decimalAt;
1963             int repeat = maxIntDigits;
1964             int minimumIntegerDigits = minIntDigits;
1965             if (repeat > 1 && repeat > minIntDigits) {
1966                 // A repeating range is defined; adjust to it as follows.
1967                 // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
1968                 // -3,-4,-5=>-6, etc. This takes into account that the
1969                 // exponent we have here is off by one from what we expect;
1970                 // it is for the format 0.MMMMMx10^n.
1971                 if (exponent >= 1) {
1972                     exponent = ((exponent - 1) / repeat) * repeat;
1973                 } else {
1974                     // integer division rounds towards 0
1975                     exponent = ((exponent - repeat) / repeat) * repeat;
1976                 }
1977                 minimumIntegerDigits = 1;
1978             } else {
1979                 // No repeating range is defined; use minimum integer digits.
1980                 exponent -= minimumIntegerDigits;
1981             }
1982 
1983             // We now output a minimum number of digits, and more if there
1984             // are more digits, up to the maximum number of digits.  We
1985             // place the decimal point after the "integer" digits, which
1986             // are the first (decimalAt - exponent) digits.
1987             int minimumDigits = minIntDigits + minFraDigits;
1988             if (minimumDigits < 0) {    // overflow?
1989                 minimumDigits = Integer.MAX_VALUE;
1990             }
1991 
1992             // The number of integer digits is handled specially if the number
1993             // is zero, since then there may be no digits.
1994             int integerDigits = digitList.isZero() ? minimumIntegerDigits :
1995                     digitList.decimalAt - exponent;
1996             if (minimumDigits < integerDigits) {
1997                 minimumDigits = integerDigits;
1998             }
1999             int totalDigits = digitList.count;
2000             if (minimumDigits > totalDigits) {
2001                 totalDigits = minimumDigits;
2002             }
2003             boolean addedDecimalSeparator = false;
2004 
2005             for (int i=0; i<totalDigits; ++i) {
2006                 if (i == integerDigits) {
2007                     // Record field information for caller.
2008                     iFieldEnd = result.length();
2009 
2010                     result.append(decimal);
2011                     addedDecimalSeparator = true;
2012 
2013                     // Record field information for caller.
2014                     fFieldStart = result.length();
2015                 }
2016                 result.append((i < digitList.count) ?
2017                               (char)(digitList.digits[i] + zeroDelta) :
2018                               zero);
2019             }
2020 
2021             if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {
2022                 // Record field information for caller.
2023                 iFieldEnd = result.length();
2024 
2025                 result.append(decimal);
2026                 addedDecimalSeparator = true;
2027 
2028                 // Record field information for caller.
2029                 fFieldStart = result.length();
2030             }
2031 
2032             // Record field information
2033             if (iFieldEnd == -1) {
2034                 iFieldEnd = result.length();
2035             }
2036             delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
2037                                iFieldStart, iFieldEnd, result);
2038             if (addedDecimalSeparator) {
2039                 delegate.formatted(Field.DECIMAL_SEPARATOR,
2040                                    Field.DECIMAL_SEPARATOR,
2041                                    iFieldEnd, fFieldStart, result);
2042             }
2043             if (fFieldStart == -1) {
2044                 fFieldStart = result.length();
2045             }
2046             delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
2047                                fFieldStart, result.length(), result);
2048 
2049             // The exponent is output using the pattern-specified minimum
2050             // exponent digits.  There is no maximum limit to the exponent
2051             // digits, since truncating the exponent would result in an
2052             // unacceptable inaccuracy.
2053             int fieldStart = result.length();
2054 
2055             result.append(symbols.getExponentSeparator());
2056 
2057             delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,
2058                                fieldStart, result.length(), result);
2059 
2060             // For zero values, we force the exponent to zero.  We
2061             // must do this here, and not earlier, because the value
2062             // is used to determine integer digit count above.
2063             if (digitList.isZero()) {
2064                 exponent = 0;
2065             }
2066 
2067             boolean negativeExponent = exponent < 0;
2068             if (negativeExponent) {
2069                 exponent = -exponent;
2070                 fieldStart = result.length();
2071                 result.append(symbols.getMinusSign());
2072                 delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
2073                                    fieldStart, result.length(), result);
2074             }
2075             digitList.set(negativeExponent, exponent);
2076 
2077             int eFieldStart = result.length();
2078 
2079             for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {
2080                 result.append(zero);
2081             }
2082             for (int i=0; i<digitList.decimalAt; ++i) {
2083                 result.append((i < digitList.count) ?
2084                           (char)(digitList.digits[i] + zeroDelta) : zero);
2085             }
2086             delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,
2087                                result.length(), result);
2088         } else {
2089             int iFieldStart = result.length();
2090 
2091             // Output the integer portion.  Here 'count' is the total
2092             // number of integer digits we will display, including both
2093             // leading zeros required to satisfy getMinimumIntegerDigits,
2094             // and actual digits present in the number.
2095             int count = minIntDigits;
2096             int digitIndex = 0; // Index into digitList.fDigits[]
2097             if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
2098                 count = digitList.decimalAt;
2099             }
2100 
2101             // Handle the case where getMaximumIntegerDigits() is smaller
2102             // than the real number of integer digits.  If this is so, we
2103             // output the least significant max integer digits.  For example,
2104             // the value 1997 printed with 2 max integer digits is just "97".
2105             if (count > maxIntDigits) {
2106                 count = maxIntDigits;
2107                 digitIndex = digitList.decimalAt - count;
2108             }
2109 
2110             int sizeBeforeIntegerPart = result.length();
2111             for (int i=count-1; i>=0; --i) {
2112                 if (i < digitList.decimalAt && digitIndex < digitList.count) {
2113                     // Output a real digit
2114                     result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
2115                 } else {
2116                     // Output a leading zero
2117                     result.append(zero);
2118                 }
2119 
2120                 // Output grouping separator if necessary.  Don't output a
2121                 // grouping separator if i==0 though; that's at the end of
2122                 // the integer part.
2123                 if (isGroupingUsed() && i>0 && (groupingSize != 0) &&
2124                     (i % groupingSize == 0)) {
2125                     int gStart = result.length();
2126                     result.append(grouping);
2127                     delegate.formatted(Field.GROUPING_SEPARATOR,
2128                                        Field.GROUPING_SEPARATOR, gStart,
2129                                        result.length(), result);
2130                 }
2131             }
2132 
2133             // Determine whether or not there are any printable fractional
2134             // digits.  If we've used up the digits we know there aren't.
2135             boolean fractionPresent = (minFraDigits > 0) ||
2136                 (!isInteger && digitIndex < digitList.count);
2137 
2138             // If there is no fraction present, and we haven't printed any
2139             // integer digits, then print a zero.  Otherwise we won't print
2140             // _any_ digits, and we won't be able to parse this string.
2141             if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
2142                 result.append(zero);
2143             }
2144 
2145             delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
2146                                iFieldStart, result.length(), result);
2147 
2148             // Output the decimal separator if we always do so.
2149             int sStart = result.length();
2150             if (decimalSeparatorAlwaysShown || fractionPresent) {
2151                 result.append(decimal);
2152             }
2153 
2154             if (sStart != result.length()) {
2155                 delegate.formatted(Field.DECIMAL_SEPARATOR,
2156                                    Field.DECIMAL_SEPARATOR,
2157                                    sStart, result.length(), result);
2158             }
2159             int fFieldStart = result.length();
2160 
2161             for (int i=0; i < maxFraDigits; ++i) {
2162                 // Here is where we escape from the loop.  We escape if we've
2163                 // output the maximum fraction digits (specified in the for
2164                 // expression above).
2165                 // We also stop when we've output the minimum digits and either:
2166                 // we have an integer, so there is no fractional stuff to
2167                 // display, or we're out of significant digits.
2168                 if (i >= minFraDigits &&
2169                     (isInteger || digitIndex >= digitList.count)) {
2170                     break;
2171                 }
2172 
2173                 // Output leading fractional zeros. These are zeros that come
2174                 // after the decimal but before any significant digits. These
2175                 // are only output if abs(number being formatted) < 1.0.
2176                 if (-1-i > (digitList.decimalAt-1)) {
2177                     result.append(zero);
2178                     continue;
2179                 }
2180 
2181                 // Output a digit, if we have any precision left, or a
2182                 // zero if we don't.  We don't want to output noise digits.
2183                 if (!isInteger && digitIndex < digitList.count) {
2184                     result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
2185                 } else {
2186                     result.append(zero);
2187                 }
2188             }
2189 
2190             // Record field information for caller.
2191             delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
2192                                fFieldStart, result.length(), result);
2193         }
2194 
2195         if (isNegative) {
2196             append(result, negativeSuffix, delegate,
2197                    getNegativeSuffixFieldPositions(), Field.SIGN);
2198         } else {
2199             append(result, positiveSuffix, delegate,
2200                    getPositiveSuffixFieldPositions(), Field.SIGN);
2201         }
2202 
2203         return result;
2204     }
2205 
2206     /**
2207      * Appends the String <code>string</code> to <code>result</code>.
2208      * <code>delegate</code> is notified of all  the
2209      * <code>FieldPosition</code>s in <code>positions</code>.
2210      * <p>
2211      * If one of the <code>FieldPosition</code>s in <code>positions</code>
2212      * identifies a <code>SIGN</code> attribute, it is mapped to
2213      * <code>signAttribute</code>. This is used
2214      * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
2215      * attribute as necessary.
2216      * <p>
2217      * This is used by <code>subformat</code> to add the prefix/suffix.
2218      *
2219     private void append(StringBuffer result, String string,
2220                         FieldDelegate delegate,
2221                         FieldPosition[] positions,
2222                         Format.Field signAttribute) {
2223         int start = result.length();
2224 
2225         if (!string.isEmpty()) {
2226             result.append(string);
2227             for (int counter = 0, max = positions.length; counter < max;
2228                  counter++) {
2229                 FieldPosition fp = positions[counter];
2230                 Format.Field attribute = fp.getFieldAttribute();
2231 
2232                 if (attribute == Field.SIGN) {
2233                     attribute = signAttribute;
2234                 }
2235                 delegate.formatted(attribute, attribute,
2236                                    start + fp.getBeginIndex(),
2237                                    start + fp.getEndIndex(), result);
2238             }
2239         }
2240     }
2241     */
2242     // END Android-removed: "fast-path formatting logic for double", subformat(), append().
2243 
2244     /**
2245      * Parses text from a string to produce a <code>Number</code>.
2246      * <p>
2247      * The method attempts to parse text starting at the index given by
2248      * <code>pos</code>.
2249      * If parsing succeeds, then the index of <code>pos</code> is updated
2250      * to the index after the last character used (parsing does not necessarily
2251      * use all characters up to the end of the string), and the parsed
2252      * number is returned. The updated <code>pos</code> can be used to
2253      * indicate the starting point for the next call to this method.
2254      * If an error occurs, then the index of <code>pos</code> is not
2255      * changed, the error index of <code>pos</code> is set to the index of
2256      * the character where the error occurred, and null is returned.
2257      * <p>
2258      * The subclass returned depends on the value of {@link #isParseBigDecimal}
2259      * as well as on the string being parsed.
2260      * <ul>
2261      *   <li>If <code>isParseBigDecimal()</code> is false (the default),
2262      *       most integer values are returned as <code>Long</code>
2263      *       objects, no matter how they are written: <code>"17"</code> and
2264      *       <code>"17.000"</code> both parse to <code>Long(17)</code>.
2265      *       Values that cannot fit into a <code>Long</code> are returned as
2266      *       <code>Double</code>s. This includes values with a fractional part,
2267      *       infinite values, <code>NaN</code>, and the value -0.0.
2268      *       <code>DecimalFormat</code> does <em>not</em> decide whether to
2269      *       return a <code>Double</code> or a <code>Long</code> based on the
2270      *       presence of a decimal separator in the source string. Doing so
2271      *       would prevent integers that overflow the mantissa of a double,
2272      *       such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
2273      *       parsed accurately.
2274      *       <p>
2275      *       Callers may use the <code>Number</code> methods
2276      *       <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
2277      *       the type they want.
2278      *   <li>If <code>isParseBigDecimal()</code> is true, values are returned
2279      *       as <code>BigDecimal</code> objects. The values are the ones
2280      *       constructed by {@link java.math.BigDecimal#BigDecimal(String)}
2281      *       for corresponding strings in locale-independent format. The
2282      *       special cases negative and positive infinity and NaN are returned
2283      *       as <code>Double</code> instances holding the values of the
2284      *       corresponding <code>Double</code> constants.
2285      * </ul>
2286      * <p>
2287      * <code>DecimalFormat</code> parses all Unicode characters that represent
2288      * decimal digits, as defined by <code>Character.digit()</code>. In
2289      * addition, <code>DecimalFormat</code> also recognizes as digits the ten
2290      * consecutive characters starting with the localized zero digit defined in
2291      * the <code>DecimalFormatSymbols</code> object.
2292      *
2293      * @param text the string to be parsed
2294      * @param pos  A <code>ParsePosition</code> object with index and error
2295      *             index information as described above.
2296      * @return     the parsed value, or <code>null</code> if the parse fails
2297      * @exception  NullPointerException if <code>text</code> or
2298      *             <code>pos</code> is null.
2299      */
2300     @Override
parse(String text, ParsePosition pos)2301     public Number parse(String text, ParsePosition pos) {
2302         // BEGIN Android-changed: Use ICU.
2303         // Return early if the parse position is bogus.
2304         /*
2305         // special case NaN
2306         if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
2307             pos.index = pos.index + symbols.getNaN().length();
2308             return Double.valueOf(Double.NaN);
2309         }
2310 
2311         boolean[] status = new boolean[STATUS_LENGTH];
2312         if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) {
2313             return null;
2314         }
2315 
2316         // special case INFINITY
2317         if (status[STATUS_INFINITE]) {
2318             if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
2319                 return Double.valueOf(Double.POSITIVE_INFINITY);
2320             } else {
2321                 return Double.valueOf(Double.NEGATIVE_INFINITY);
2322             }
2323         }
2324 
2325         if (multiplier == 0) {
2326             if (digitList.isZero()) {
2327                 return Double.valueOf(Double.NaN);
2328             } else if (status[STATUS_POSITIVE]) {
2329                 return Double.valueOf(Double.POSITIVE_INFINITY);
2330             } else {
2331                 return Double.valueOf(Double.NEGATIVE_INFINITY);
2332             }
2333         }
2334 
2335         if (isParseBigDecimal()) {
2336             BigDecimal bigDecimalResult = digitList.getBigDecimal();
2337 
2338             if (multiplier != 1) {
2339                 try {
2340                     bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier());
2341                 }
2342                 catch (ArithmeticException e) {  // non-terminating decimal expansion
2343                     bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode);
2344                 }
2345             }
2346 
2347             if (!status[STATUS_POSITIVE]) {
2348                 bigDecimalResult = bigDecimalResult.negate();
2349             }
2350             return bigDecimalResult;
2351         } else {
2352             boolean gotDouble = true;
2353             boolean gotLongMinimum = false;
2354             double  doubleResult = 0.0;
2355             long    longResult = 0;
2356 
2357             // Finally, have DigitList parse the digits into a value.
2358             if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
2359                 gotDouble = false;
2360                 longResult = digitList.getLong();
2361                 if (longResult < 0) {  // got Long.MIN_VALUE
2362                     gotLongMinimum = true;
2363                 }
2364             } else {
2365                 doubleResult = digitList.getDouble();
2366             }
2367 
2368             // Divide by multiplier. We have to be careful here not to do
2369             // unneeded conversions between double and long.
2370             if (multiplier != 1) {
2371                 if (gotDouble) {
2372                     doubleResult /= multiplier;
2373                 } else {
2374                     // Avoid converting to double if we can
2375                     if (longResult % multiplier == 0) {
2376                         longResult /= multiplier;
2377                     } else {
2378                         doubleResult = ((double)longResult) / multiplier;
2379                         gotDouble = true;
2380                     }
2381                 }
2382             }
2383 
2384             if (!status[STATUS_POSITIVE] && !gotLongMinimum) {
2385                 doubleResult = -doubleResult;
2386                 longResult = -longResult;
2387             }
2388 
2389             // At this point, if we divided the result by the multiplier, the
2390             // result may fit into a long.  We check for this case and return
2391             // a long if possible.
2392             // We must do this AFTER applying the negative (if appropriate)
2393             // in order to handle the case of LONG_MIN; otherwise, if we do
2394             // this with a positive value -LONG_MIN, the double is > 0, but
2395             // the long is < 0. We also must retain a double in the case of
2396             // -0.0, which will compare as == to a long 0 cast to a double
2397             // (bug 4162852).
2398             if (multiplier != 1 && gotDouble) {
2399                 longResult = (long)doubleResult;
2400                 gotDouble = ((doubleResult != (double)longResult) ||
2401                             (doubleResult == 0.0 && 1/doubleResult < 0.0)) &&
2402                             !isParseIntegerOnly();
2403             }
2404 
2405             // cast inside of ?: because of binary numeric promotion, JLS 15.25
2406             return gotDouble ? (Number)doubleResult : (Number)longResult;
2407         }
2408         */
2409         if (pos.index < 0 || pos.index >= text.length()) {
2410             return null;
2411         }
2412 
2413         // This might return android.icu.math.BigDecimal, java.math.BigInteger or a primitive type.
2414         Number number = icuDecimalFormat.parse(text, pos);
2415         if (number == null) {
2416             return null;
2417         }
2418         if (isParseBigDecimal()) {
2419             if (number instanceof Long) {
2420                 return new BigDecimal(number.longValue());
2421             }
2422             if ((number instanceof Double) && !((Double) number).isInfinite()
2423                     && !((Double) number).isNaN()) {
2424                 return new BigDecimal(number.toString());
2425             }
2426             if ((number instanceof Double) &&
2427                     (((Double) number).isNaN() || ((Double) number).isInfinite())) {
2428                 return number;
2429             }
2430             if (number instanceof android.icu.math.BigDecimal) {
2431                 return ((android.icu.math.BigDecimal) number).toBigDecimal();
2432             }
2433         }
2434         if ((number instanceof android.icu.math.BigDecimal) || (number instanceof BigInteger)) {
2435             return number.doubleValue();
2436         }
2437         if (isParseIntegerOnly() && number.equals(new Double(-0.0))) {
2438             return 0L;
2439         }
2440         return number;
2441         // END Android-changed: Use ICU.
2442     }
2443 
2444     // BEGIN Android-removed: Unused private helpers.
2445     /*
2446     /**
2447      * Return a BigInteger multiplier.
2448      *
2449     private BigInteger getBigIntegerMultiplier() {
2450         if (bigIntegerMultiplier == null) {
2451             bigIntegerMultiplier = BigInteger.valueOf(multiplier);
2452         }
2453         return bigIntegerMultiplier;
2454     }
2455     private transient BigInteger bigIntegerMultiplier;
2456 
2457     /**
2458      * Return a BigDecimal multiplier.
2459      *
2460     private BigDecimal getBigDecimalMultiplier() {
2461         if (bigDecimalMultiplier == null) {
2462             bigDecimalMultiplier = new BigDecimal(multiplier);
2463         }
2464         return bigDecimalMultiplier;
2465     }
2466     private transient BigDecimal bigDecimalMultiplier;
2467 
2468     private static final int STATUS_INFINITE = 0;
2469     private static final int STATUS_POSITIVE = 1;
2470     private static final int STATUS_LENGTH   = 2;
2471 
2472     /**
2473      * Parse the given text into a number.  The text is parsed beginning at
2474      * parsePosition, until an unparseable character is seen.
2475      * @param text The string to parse.
2476      * @param parsePosition The position at which to being parsing.  Upon
2477      * return, the first unparseable character.
2478      * @param digits The DigitList to set to the parsed value.
2479      * @param isExponent If true, parse an exponent.  This means no
2480      * infinite values and integer only.
2481      * @param status Upon return contains boolean status flags indicating
2482      * whether the value was infinite and whether it was positive.
2483      *
2484     private final boolean subparse(String text, ParsePosition parsePosition,
2485                    String positivePrefix, String negativePrefix,
2486                    DigitList digits, boolean isExponent,
2487                    boolean status[]) {
2488         int position = parsePosition.index;
2489         int oldStart = parsePosition.index;
2490         int backup;
2491         boolean gotPositive, gotNegative;
2492 
2493         // check for positivePrefix; take longest
2494         gotPositive = text.regionMatches(position, positivePrefix, 0,
2495                                          positivePrefix.length());
2496         gotNegative = text.regionMatches(position, negativePrefix, 0,
2497                                          negativePrefix.length());
2498 
2499         if (gotPositive && gotNegative) {
2500             if (positivePrefix.length() > negativePrefix.length()) {
2501                 gotNegative = false;
2502             } else if (positivePrefix.length() < negativePrefix.length()) {
2503                 gotPositive = false;
2504             }
2505         }
2506 
2507         if (gotPositive) {
2508             position += positivePrefix.length();
2509         } else if (gotNegative) {
2510             position += negativePrefix.length();
2511         } else {
2512             parsePosition.errorIndex = position;
2513             return false;
2514         }
2515 
2516         // process digits or Inf, find decimal position
2517         status[STATUS_INFINITE] = false;
2518         if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
2519                           symbols.getInfinity().length())) {
2520             position += symbols.getInfinity().length();
2521             status[STATUS_INFINITE] = true;
2522         } else {
2523             // We now have a string of digits, possibly with grouping symbols,
2524             // and decimal points.  We want to process these into a DigitList.
2525             // We don't want to put a bunch of leading zeros into the DigitList
2526             // though, so we keep track of the location of the decimal point,
2527             // put only significant digits into the DigitList, and adjust the
2528             // exponent as needed.
2529 
2530             digits.decimalAt = digits.count = 0;
2531             char zero = symbols.getZeroDigit();
2532             char decimal = isCurrencyFormat ?
2533                 symbols.getMonetaryDecimalSeparator() :
2534                 symbols.getDecimalSeparator();
2535             char grouping = symbols.getGroupingSeparator();
2536             String exponentString = symbols.getExponentSeparator();
2537             boolean sawDecimal = false;
2538             boolean sawExponent = false;
2539             boolean sawDigit = false;
2540             int exponent = 0; // Set to the exponent value, if any
2541 
2542             // We have to track digitCount ourselves, because digits.count will
2543             // pin when the maximum allowable digits is reached.
2544             int digitCount = 0;
2545 
2546             backup = -1;
2547             for (; position < text.length(); ++position) {
2548                 char ch = text.charAt(position);
2549 
2550                 /* We recognize all digit ranges, not only the Latin digit range
2551                  * '0'..'9'.  We do so by using the Character.digit() method,
2552                  * which converts a valid Unicode digit to the range 0..9.
2553                  *
2554                  * The character 'ch' may be a digit.  If so, place its value
2555                  * from 0 to 9 in 'digit'.  First try using the locale digit,
2556                  * which may or MAY NOT be a standard Unicode digit range.  If
2557                  * this fails, try using the standard Unicode digit ranges by
2558                  * calling Character.digit().  If this also fails, digit will
2559                  * have a value outside the range 0..9.
2560                  *
2561                 int digit = ch - zero;
2562                 if (digit < 0 || digit > 9) {
2563                     digit = Character.digit(ch, 10);
2564                 }
2565 
2566                 if (digit == 0) {
2567                     // Cancel out backup setting (see grouping handler below)
2568                     backup = -1; // Do this BEFORE continue statement below!!!
2569                     sawDigit = true;
2570 
2571                     // Handle leading zeros
2572                     if (digits.count == 0) {
2573                         // Ignore leading zeros in integer part of number.
2574                         if (!sawDecimal) {
2575                             continue;
2576                         }
2577 
2578                         // If we have seen the decimal, but no significant
2579                         // digits yet, then we account for leading zeros by
2580                         // decrementing the digits.decimalAt into negative
2581                         // values.
2582                         --digits.decimalAt;
2583                     } else {
2584                         ++digitCount;
2585                         digits.append((char)(digit + '0'));
2586                     }
2587                 } else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above
2588                     sawDigit = true;
2589                     ++digitCount;
2590                     digits.append((char)(digit + '0'));
2591 
2592                     // Cancel out backup setting (see grouping handler below)
2593                     backup = -1;
2594                 } else if (!isExponent && ch == decimal) {
2595                     // If we're only parsing integers, or if we ALREADY saw the
2596                     // decimal, then don't parse this one.
2597                     if (isParseIntegerOnly() || sawDecimal) {
2598                         break;
2599                     }
2600                     digits.decimalAt = digitCount; // Not digits.count!
2601                     sawDecimal = true;
2602                 } else if (!isExponent && ch == grouping && isGroupingUsed()) {
2603                     if (sawDecimal) {
2604                         break;
2605                     }
2606                     // Ignore grouping characters, if we are using them, but
2607                     // require that they be followed by a digit.  Otherwise
2608                     // we backup and reprocess them.
2609                     backup = position;
2610                 } else if (!isExponent && text.regionMatches(position, exponentString, 0, exponentString.length())
2611                              && !sawExponent) {
2612                     // Process the exponent by recursively calling this method.
2613                      ParsePosition pos = new ParsePosition(position + exponentString.length());
2614                     boolean[] stat = new boolean[STATUS_LENGTH];
2615                     DigitList exponentDigits = new DigitList();
2616 
2617                     if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
2618                         exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
2619                         position = pos.index; // Advance past the exponent
2620                         exponent = (int)exponentDigits.getLong();
2621                         if (!stat[STATUS_POSITIVE]) {
2622                             exponent = -exponent;
2623                         }
2624                         sawExponent = true;
2625                     }
2626                     break; // Whether we fail or succeed, we exit this loop
2627                 } else {
2628                     break;
2629                 }
2630             }
2631 
2632             if (backup != -1) {
2633                 position = backup;
2634             }
2635 
2636             // If there was no decimal point we have an integer
2637             if (!sawDecimal) {
2638                 digits.decimalAt = digitCount; // Not digits.count!
2639             }
2640 
2641             // Adjust for exponent, if any
2642             digits.decimalAt += exponent;
2643 
2644             // If none of the text string was recognized.  For example, parse
2645             // "x" with pattern "#0.00" (return index and error index both 0)
2646             // parse "$" with pattern "$#0.00". (return index 0 and error
2647             // index 1).
2648             if (!sawDigit && digitCount == 0) {
2649                 parsePosition.index = oldStart;
2650                 parsePosition.errorIndex = oldStart;
2651                 return false;
2652             }
2653         }
2654 
2655         // check for suffix
2656         if (!isExponent) {
2657             if (gotPositive) {
2658                 gotPositive = text.regionMatches(position,positiveSuffix,0,
2659                                                  positiveSuffix.length());
2660             }
2661             if (gotNegative) {
2662                 gotNegative = text.regionMatches(position,negativeSuffix,0,
2663                                                  negativeSuffix.length());
2664             }
2665 
2666         // if both match, take longest
2667         if (gotPositive && gotNegative) {
2668             if (positiveSuffix.length() > negativeSuffix.length()) {
2669                 gotNegative = false;
2670             } else if (positiveSuffix.length() < negativeSuffix.length()) {
2671                 gotPositive = false;
2672             }
2673         }
2674 
2675         // fail if neither or both
2676         if (gotPositive == gotNegative) {
2677             parsePosition.errorIndex = position;
2678             return false;
2679         }
2680 
2681         parsePosition.index = position +
2682             (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
2683         } else {
2684             parsePosition.index = position;
2685         }
2686 
2687         status[STATUS_POSITIVE] = gotPositive;
2688         if (parsePosition.index == oldStart) {
2689             parsePosition.errorIndex = position;
2690             return false;
2691         }
2692         return true;
2693     }
2694     */
2695     // END Android-removed: Unused private helpers.
2696 
2697     /**
2698      * Returns a copy of the decimal format symbols, which is generally not
2699      * changed by the programmer or user.
2700      * @return a copy of the desired DecimalFormatSymbols
2701      * @see java.text.DecimalFormatSymbols
2702      */
getDecimalFormatSymbols()2703     public DecimalFormatSymbols getDecimalFormatSymbols() {
2704         // BEGIN Android-changed: Use ICU.
2705         /*
2706         try {
2707             // don't allow multiple references
2708             return (DecimalFormatSymbols) symbols.clone();
2709         } catch (Exception foo) {
2710             return null; // should never happen
2711         }
2712         */
2713         return DecimalFormatSymbols.fromIcuInstance(icuDecimalFormat.getDecimalFormatSymbols());
2714         // END Android-changed: Use ICU.
2715     }
2716 
2717 
2718     /**
2719      * Sets the decimal format symbols, which is generally not changed
2720      * by the programmer or user.
2721      * @param newSymbols desired DecimalFormatSymbols
2722      * @see java.text.DecimalFormatSymbols
2723      */
setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)2724     public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
2725         try {
2726             // don't allow multiple references
2727             symbols = (DecimalFormatSymbols) newSymbols.clone();
2728             // BEGIN Android-changed: Use ICU.
2729             /*
2730             expandAffixes();
2731             fastPathCheckNeeded = true;
2732             */
2733             icuDecimalFormat.setDecimalFormatSymbols(symbols.getIcuDecimalFormatSymbols());
2734             // END Android-changed: Use ICU.
2735         } catch (Exception foo) {
2736             // should never happen
2737         }
2738     }
2739 
2740     /**
2741      * Get the positive prefix.
2742      * <P>Examples: +123, $123, sFr123
2743      *
2744      * @return the positive prefix
2745      */
getPositivePrefix()2746     public String getPositivePrefix () {
2747         // Android-changed: Use ICU.
2748         // return positivePrefix;
2749         return icuDecimalFormat.getPositivePrefix();
2750     }
2751 
2752     /**
2753      * Set the positive prefix.
2754      * <P>Examples: +123, $123, sFr123
2755      *
2756      * @param newValue the new positive prefix
2757      */
setPositivePrefix(String newValue)2758     public void setPositivePrefix (String newValue) {
2759         // BEGIN Android-changed: Use ICU.
2760         /*
2761         positivePrefix = newValue;
2762         posPrefixPattern = null;
2763         positivePrefixFieldPositions = null;
2764         fastPathCheckNeeded = true;
2765         */
2766         icuDecimalFormat.setPositivePrefix(newValue);
2767         // END Android-changed: Use ICU.
2768     }
2769 
2770     // BEGIN Android-removed: private helper getPositivePrefixFieldPositions().
2771     /*
2772     /**
2773      * Returns the FieldPositions of the fields in the prefix used for
2774      * positive numbers. This is not used if the user has explicitly set
2775      * a positive prefix via <code>setPositivePrefix</code>. This is
2776      * lazily created.
2777      *
2778      * @return FieldPositions in positive prefix
2779      *
2780     private FieldPosition[] getPositivePrefixFieldPositions() {
2781         if (positivePrefixFieldPositions == null) {
2782             if (posPrefixPattern != null) {
2783                 positivePrefixFieldPositions = expandAffix(posPrefixPattern);
2784             } else {
2785                 positivePrefixFieldPositions = EmptyFieldPositionArray;
2786             }
2787         }
2788         return positivePrefixFieldPositions;
2789     }
2790     */
2791     // END Android-removed: private helper getPositivePrefixFieldPositions().
2792 
2793     /**
2794      * Get the negative prefix.
2795      * <P>Examples: -123, ($123) (with negative suffix), sFr-123
2796      *
2797      * @return the negative prefix
2798      */
getNegativePrefix()2799     public String getNegativePrefix () {
2800         // Android-changed: Use ICU.
2801         // return negativePrefix;
2802         return icuDecimalFormat.getNegativePrefix();
2803     }
2804 
2805     /**
2806      * Set the negative prefix.
2807      * <P>Examples: -123, ($123) (with negative suffix), sFr-123
2808      *
2809      * @param newValue the new negative prefix
2810      */
setNegativePrefix(String newValue)2811     public void setNegativePrefix (String newValue) {
2812         // BEGIN Android-changed: Use ICU.
2813         /*
2814         negativePrefix = newValue;
2815         negPrefixPattern = null;
2816         fastPathCheckNeeded = true;
2817         */
2818         icuDecimalFormat.setNegativePrefix(newValue);
2819         // END Android-changed: Use ICU.
2820     }
2821 
2822     // BEGIN Android-removed: private helper getNegativePrefixFieldPositions().
2823     /*
2824     /**
2825      * Returns the FieldPositions of the fields in the prefix used for
2826      * negative numbers. This is not used if the user has explicitly set
2827      * a negative prefix via <code>setNegativePrefix</code>. This is
2828      * lazily created.
2829      *
2830      * @return FieldPositions in positive prefix
2831      *
2832     private FieldPosition[] getNegativePrefixFieldPositions() {
2833         if (negativePrefixFieldPositions == null) {
2834             if (negPrefixPattern != null) {
2835                 negativePrefixFieldPositions = expandAffix(negPrefixPattern);
2836             } else {
2837                 negativePrefixFieldPositions = EmptyFieldPositionArray;
2838             }
2839         }
2840         return negativePrefixFieldPositions;
2841     }
2842     */
2843     // END Android-removed: private helper getNegativePrefixFieldPositions().
2844 
2845     /**
2846      * Get the positive suffix.
2847      * <P>Example: 123%
2848      *
2849      * @return the positive suffix
2850      */
getPositiveSuffix()2851     public String getPositiveSuffix () {
2852         // Android-changed: Use ICU.
2853         // return positiveSuffix;
2854         return icuDecimalFormat.getPositiveSuffix();
2855     }
2856 
2857     /**
2858      * Set the positive suffix.
2859      * <P>Example: 123%
2860      *
2861      * @param newValue the new positive suffix
2862      */
setPositiveSuffix(String newValue)2863     public void setPositiveSuffix (String newValue) {
2864         // BEGIN Android-changed: Use ICU.
2865         /*
2866         positiveSuffix = newValue;
2867         posSuffixPattern = null;
2868         fastPathCheckNeeded = true;
2869         */
2870         icuDecimalFormat.setPositiveSuffix(newValue);
2871         // END Android-changed: Use ICU.
2872     }
2873 
2874     // BEGIN Android-removed: private helper getPositiveSuffixFieldPositions().
2875     /*
2876     /**
2877      * Returns the FieldPositions of the fields in the suffix used for
2878      * positive numbers. This is not used if the user has explicitly set
2879      * a positive suffix via <code>setPositiveSuffix</code>. This is
2880      * lazily created.
2881      *
2882      * @return FieldPositions in positive prefix
2883      *
2884     private FieldPosition[] getPositiveSuffixFieldPositions() {
2885         if (positiveSuffixFieldPositions == null) {
2886             if (posSuffixPattern != null) {
2887                 positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
2888             } else {
2889                 positiveSuffixFieldPositions = EmptyFieldPositionArray;
2890             }
2891         }
2892         return positiveSuffixFieldPositions;
2893     }
2894     */
2895     // END Android-removed: private helper getPositiveSuffixFieldPositions().
2896 
2897     /**
2898      * Get the negative suffix.
2899      * <P>Examples: -123%, ($123) (with positive suffixes)
2900      *
2901      * @return the negative suffix
2902      */
getNegativeSuffix()2903     public String getNegativeSuffix () {
2904         // Android-changed: Use ICU.
2905         // return negativeSuffix;
2906         return icuDecimalFormat.getNegativeSuffix();
2907     }
2908 
2909     /**
2910      * Set the negative suffix.
2911      * <P>Examples: 123%
2912      *
2913      * @param newValue the new negative suffix
2914      */
setNegativeSuffix(String newValue)2915     public void setNegativeSuffix (String newValue) {
2916         // BEGIN Android-changed: Use ICU.
2917         /*
2918         negativeSuffix = newValue;
2919         negSuffixPattern = null;
2920         fastPathCheckNeeded = true;
2921          */
2922         icuDecimalFormat.setNegativeSuffix(newValue);
2923         // END Android-changed: Use ICU.
2924     }
2925 
2926     // BEGIN Android-removed: private helper getNegativeSuffixFieldPositions().
2927     /*
2928     /**
2929      * Returns the FieldPositions of the fields in the suffix used for
2930      * negative numbers. This is not used if the user has explicitly set
2931      * a negative suffix via <code>setNegativeSuffix</code>. This is
2932      * lazily created.
2933      *
2934      * @return FieldPositions in positive prefix
2935      *
2936     private FieldPosition[] getNegativeSuffixFieldPositions() {
2937         if (negativeSuffixFieldPositions == null) {
2938             if (negSuffixPattern != null) {
2939                 negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
2940             } else {
2941                 negativeSuffixFieldPositions = EmptyFieldPositionArray;
2942             }
2943         }
2944         return negativeSuffixFieldPositions;
2945     }
2946     */
2947     // END Android-removed: private helper getNegativeSuffixFieldPositions().
2948 
2949     /**
2950      * Gets the multiplier for use in percent, per mille, and similar
2951      * formats.
2952      *
2953      * @return the multiplier
2954      * @see #setMultiplier(int)
2955      */
getMultiplier()2956     public int getMultiplier () {
2957         // Android-changed: Use ICU.
2958         // return multiplier;
2959         return icuDecimalFormat.getMultiplier();
2960     }
2961 
2962     /**
2963      * Sets the multiplier for use in percent, per mille, and similar
2964      * formats.
2965      * For a percent format, set the multiplier to 100 and the suffixes to
2966      * have '%' (for Arabic, use the Arabic percent sign).
2967      * For a per mille format, set the multiplier to 1000 and the suffixes to
2968      * have '&#92;u2030'.
2969      *
2970      * <P>Example: with multiplier 100, 1.23 is formatted as "123", and
2971      * "123" is parsed into 1.23.
2972      *
2973      * @param newValue the new multiplier
2974      * @see #getMultiplier
2975      */
setMultiplier(int newValue)2976     public void setMultiplier (int newValue) {
2977         // BEGIN Android-changed: Use ICU.
2978         /*
2979         multiplier = newValue;
2980         bigDecimalMultiplier = null;
2981         bigIntegerMultiplier = null;
2982         fastPathCheckNeeded = true;
2983         */
2984         icuDecimalFormat.setMultiplier(newValue);
2985         // END Android-changed: Use ICU.
2986     }
2987 
2988     /**
2989      * {@inheritDoc}
2990      */
2991     @Override
setGroupingUsed(boolean newValue)2992     public void setGroupingUsed(boolean newValue) {
2993         // BEGIN Android-changed: Use ICU.
2994         /*
2995         super.setGroupingUsed(newValue);
2996         fastPathCheckNeeded = true;
2997         */
2998         icuDecimalFormat.setGroupingUsed(newValue);
2999         // END Android-changed: Use ICU.
3000     }
3001 
3002     // BEGIN Android-added: isGroupingUsed() override delegating to ICU.
3003     /**
3004      * {@inheritDoc}
3005      */
3006     @Override
isGroupingUsed()3007     public boolean isGroupingUsed() {
3008         return icuDecimalFormat.isGroupingUsed();
3009     }
3010     // END Android-added: isGroupingUsed() override delegating to ICU.
3011 
3012     /**
3013      * Return the grouping size. Grouping size is the number of digits between
3014      * grouping separators in the integer portion of a number.  For example,
3015      * in the number "123,456.78", the grouping size is 3.
3016      *
3017      * @return the grouping size
3018      * @see #setGroupingSize
3019      * @see java.text.NumberFormat#isGroupingUsed
3020      * @see java.text.DecimalFormatSymbols#getGroupingSeparator
3021      */
getGroupingSize()3022     public int getGroupingSize () {
3023         // Android-changed: Use ICU.
3024         // return groupingSize;
3025         return icuDecimalFormat.getGroupingSize();
3026     }
3027 
3028     /**
3029      * Set the grouping size. Grouping size is the number of digits between
3030      * grouping separators in the integer portion of a number.  For example,
3031      * in the number "123,456.78", the grouping size is 3.
3032      * <br>
3033      * The value passed in is converted to a byte, which may lose information.
3034      *
3035      * @param newValue the new grouping size
3036      * @see #getGroupingSize
3037      * @see java.text.NumberFormat#setGroupingUsed
3038      * @see java.text.DecimalFormatSymbols#setGroupingSeparator
3039      */
setGroupingSize(int newValue)3040     public void setGroupingSize (int newValue) {
3041         // BEGIN Android-changed: Use ICU.
3042         /*
3043         groupingSize = (byte)newValue;
3044         fastPathCheckNeeded = true;
3045         */
3046         icuDecimalFormat.setGroupingSize(newValue);
3047         // END Android-changed: Use ICU.
3048     }
3049 
3050     /**
3051      * Allows you to get the behavior of the decimal separator with integers.
3052      * (The decimal separator will always appear with decimals.)
3053      * <P>Example: Decimal ON: 12345 &rarr; 12345.; OFF: 12345 &rarr; 12345
3054      *
3055      * @return {@code true} if the decimal separator is always shown;
3056      *         {@code false} otherwise
3057      */
isDecimalSeparatorAlwaysShown()3058     public boolean isDecimalSeparatorAlwaysShown() {
3059         // Android-changed: Use ICU.
3060         // return decimalSeparatorAlwaysShown;
3061         return icuDecimalFormat.isDecimalSeparatorAlwaysShown();
3062     }
3063 
3064     /**
3065      * Allows you to set the behavior of the decimal separator with integers.
3066      * (The decimal separator will always appear with decimals.)
3067      * <P>Example: Decimal ON: 12345 &rarr; 12345.; OFF: 12345 &rarr; 12345
3068      *
3069      * @param newValue {@code true} if the decimal separator is always shown;
3070      *                 {@code false} otherwise
3071      */
setDecimalSeparatorAlwaysShown(boolean newValue)3072     public void setDecimalSeparatorAlwaysShown(boolean newValue) {
3073         // BEGIN Android-changed: Use ICU.
3074         /*
3075         decimalSeparatorAlwaysShown = newValue;
3076         fastPathCheckNeeded = true;
3077         */
3078         icuDecimalFormat.setDecimalSeparatorAlwaysShown(newValue);
3079         // END Android-changed: Use ICU.
3080     }
3081 
3082     /**
3083      * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
3084      * method returns <code>BigDecimal</code>. The default value is false.
3085      *
3086      * @return {@code true} if the parse method returns BigDecimal;
3087      *         {@code false} otherwise
3088      * @see #setParseBigDecimal
3089      * @since 1.5
3090      */
isParseBigDecimal()3091     public boolean isParseBigDecimal() {
3092         // Android-changed: Use ICU.
3093         // return parseBigDecimal;
3094         return icuDecimalFormat.isParseBigDecimal();
3095     }
3096 
3097     /**
3098      * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
3099      * method returns <code>BigDecimal</code>.
3100      *
3101      * @param newValue {@code true} if the parse method returns BigDecimal;
3102      *                 {@code false} otherwise
3103      * @see #isParseBigDecimal
3104      * @since 1.5
3105      */
setParseBigDecimal(boolean newValue)3106     public void setParseBigDecimal(boolean newValue) {
3107         // Android-changed: Use ICU.
3108         // parseBigDecimal = newValue;
3109         icuDecimalFormat.setParseBigDecimal(newValue);
3110     }
3111 
3112     // BEGIN Android-added: setParseIntegerOnly()/isParseIntegerOnly() overrides delegating to ICU.
3113     /**
3114      * {@inheritDoc}
3115      */
3116     @Override
isParseIntegerOnly()3117     public boolean isParseIntegerOnly() {
3118         return icuDecimalFormat.isParseIntegerOnly();
3119     }
3120 
3121     /**
3122      * {@inheritDoc}
3123      */
3124     @Override
setParseIntegerOnly(boolean value)3125     public void setParseIntegerOnly(boolean value) {
3126         super.setParseIntegerOnly(value);
3127         icuDecimalFormat.setParseIntegerOnly(value);
3128     }
3129     // END Android-added: setParseIntegerOnly()/isParseIntegerOnly() overrides delegating to ICU.
3130 
3131     /**
3132      * Standard override; no change in semantics.
3133      */
3134     @Override
clone()3135     public Object clone() {
3136         // BEGIN Android-changed: Use ICU, remove fast path related code.
3137         /*
3138         DecimalFormat other = (DecimalFormat) super.clone();
3139         other.symbols = (DecimalFormatSymbols) symbols.clone();
3140         other.digitList = (DigitList) digitList.clone();
3141 
3142         // Fast-path is almost stateless algorithm. The only logical state is the
3143         // isFastPath flag. In addition fastPathCheckNeeded is a sentinel flag
3144         // that forces recalculation of all fast-path fields when set to true.
3145         //
3146         // There is thus no need to clone all the fast-path fields.
3147         // We just only need to set fastPathCheckNeeded to true when cloning,
3148         // and init fastPathData to null as if it were a truly new instance.
3149         // Every fast-path field will be recalculated (only once) at next usage of
3150         // fast-path algorithm.
3151         other.fastPathCheckNeeded = true;
3152         other.isFastPath = false;
3153         other.fastPathData = null;
3154 
3155         return other;
3156         */
3157         try {
3158             DecimalFormat other = (DecimalFormat) super.clone();
3159             other.icuDecimalFormat = (android.icu.text.DecimalFormat) icuDecimalFormat.clone();
3160             other.symbols = (DecimalFormatSymbols) symbols.clone();
3161             return other;
3162         } catch (Exception e) {
3163             throw new InternalError();
3164         }
3165         // END Android-changed: Use ICU, remove fast path related code.
3166     }
3167 
3168     /**
3169      * Overrides equals
3170      */
3171     @Override
equals(Object obj)3172     public boolean equals(Object obj)
3173     {
3174     // BEGIN Android-changed: re-implement equals() using ICU fields.
3175         /*
3176         if (obj == null)
3177             return false;
3178         if (!super.equals(obj))
3179             return false; // super does class check
3180         DecimalFormat other = (DecimalFormat) obj;
3181         return ((posPrefixPattern == other.posPrefixPattern &&
3182                  positivePrefix.equals(other.positivePrefix))
3183                 || (posPrefixPattern != null &&
3184                     posPrefixPattern.equals(other.posPrefixPattern)))
3185             && ((posSuffixPattern == other.posSuffixPattern &&
3186                  positiveSuffix.equals(other.positiveSuffix))
3187                 || (posSuffixPattern != null &&
3188                     posSuffixPattern.equals(other.posSuffixPattern)))
3189             && ((negPrefixPattern == other.negPrefixPattern &&
3190                  negativePrefix.equals(other.negativePrefix))
3191                 || (negPrefixPattern != null &&
3192                     negPrefixPattern.equals(other.negPrefixPattern)))
3193             && ((negSuffixPattern == other.negSuffixPattern &&
3194                  negativeSuffix.equals(other.negativeSuffix))
3195                 || (negSuffixPattern != null &&
3196                     negSuffixPattern.equals(other.negSuffixPattern)))
3197             && multiplier == other.multiplier
3198             && groupingSize == other.groupingSize
3199             && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
3200             && parseBigDecimal == other.parseBigDecimal
3201             && useExponentialNotation == other.useExponentialNotation
3202             && (!useExponentialNotation ||
3203                 minExponentDigits == other.minExponentDigits)
3204             && maximumIntegerDigits == other.maximumIntegerDigits
3205             && minimumIntegerDigits == other.minimumIntegerDigits
3206             && maximumFractionDigits == other.maximumFractionDigits
3207             && minimumFractionDigits == other.minimumFractionDigits
3208             && roundingMode == other.roundingMode
3209             && symbols.equals(other.symbols);
3210         */
3211         if (obj == null) {
3212             return false;
3213         }
3214         if (this == obj) {
3215             return true;
3216         }
3217         if (!(obj instanceof DecimalFormat)) {
3218             return false;
3219         }
3220         DecimalFormat other = (DecimalFormat) obj;
3221         return icuDecimalFormat.equals(other.icuDecimalFormat)
3222             && compareIcuRoundingIncrement(other.icuDecimalFormat);
3223     }
3224 
compareIcuRoundingIncrement(android.icu.text.DecimalFormat other)3225     private boolean compareIcuRoundingIncrement(android.icu.text.DecimalFormat other) {
3226         BigDecimal increment = this.icuDecimalFormat.getRoundingIncrement();
3227         if (increment != null) {
3228             return (other.getRoundingIncrement() != null)
3229                 && increment.equals(other.getRoundingIncrement());
3230         }
3231         return other.getRoundingIncrement() == null;
3232     }
3233     // END Android-changed: re-implement equals() using ICU fields.
3234 
3235     /**
3236      * Overrides hashCode
3237      */
3238     @Override
hashCode()3239     public int hashCode() {
3240         // Android-changed: use getPositivePrefix() instead of positivePrefix field.
3241         // return super.hashCode() * 37 + positivePrefix.hashCode();
3242         return super.hashCode() * 37 + getPositivePrefix().hashCode();
3243         // just enough fields for a reasonable distribution
3244     }
3245 
3246     /**
3247      * Synthesizes a pattern string that represents the current state
3248      * of this Format object.
3249      *
3250      * @return a pattern string
3251      * @see #applyPattern
3252      */
toPattern()3253     public String toPattern() {
3254         // Android-changed: use ICU.
3255         // return toPattern( false );
3256         return icuDecimalFormat.toPattern();
3257     }
3258 
3259     /**
3260      * Synthesizes a localized pattern string that represents the current
3261      * state of this Format object.
3262      *
3263      * @return a localized pattern string
3264      * @see #applyPattern
3265      */
toLocalizedPattern()3266     public String toLocalizedPattern() {
3267         // Android-changed: use ICU.
3268         // return toPattern( true );
3269         return icuDecimalFormat.toLocalizedPattern();
3270     }
3271 
3272     // BEGIN Android-removed: Unused private helpers.
3273     /*
3274     /**
3275      * Expand the affix pattern strings into the expanded affix strings.  If any
3276      * affix pattern string is null, do not expand it.  This method should be
3277      * called any time the symbols or the affix patterns change in order to keep
3278      * the expanded affix strings up to date.
3279      *
3280     private void expandAffixes() {
3281         // Reuse one StringBuffer for better performance
3282         StringBuffer buffer = new StringBuffer();
3283         if (posPrefixPattern != null) {
3284             positivePrefix = expandAffix(posPrefixPattern, buffer);
3285             positivePrefixFieldPositions = null;
3286         }
3287         if (posSuffixPattern != null) {
3288             positiveSuffix = expandAffix(posSuffixPattern, buffer);
3289             positiveSuffixFieldPositions = null;
3290         }
3291         if (negPrefixPattern != null) {
3292             negativePrefix = expandAffix(negPrefixPattern, buffer);
3293             negativePrefixFieldPositions = null;
3294         }
3295         if (negSuffixPattern != null) {
3296             negativeSuffix = expandAffix(negSuffixPattern, buffer);
3297             negativeSuffixFieldPositions = null;
3298         }
3299     }
3300 
3301     /**
3302      * Expand an affix pattern into an affix string.  All characters in the
3303      * pattern are literal unless prefixed by QUOTE.  The following characters
3304      * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
3305      * PATTERN_MINUS, and CURRENCY_SIGN.  If CURRENCY_SIGN is doubled (QUOTE +
3306      * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
3307      * currency code.  Any other character after a QUOTE represents itself.
3308      * QUOTE must be followed by another character; QUOTE may not occur by
3309      * itself at the end of the pattern.
3310      *
3311      * @param pattern the non-null, possibly empty pattern
3312      * @param buffer a scratch StringBuffer; its contents will be lost
3313      * @return the expanded equivalent of pattern
3314      *
3315     private String expandAffix(String pattern, StringBuffer buffer) {
3316         buffer.setLength(0);
3317         for (int i=0; i<pattern.length(); ) {
3318             char c = pattern.charAt(i++);
3319             if (c == QUOTE) {
3320                 c = pattern.charAt(i++);
3321                 switch (c) {
3322                 case CURRENCY_SIGN:
3323                     if (i<pattern.length() &&
3324                         pattern.charAt(i) == CURRENCY_SIGN) {
3325                         ++i;
3326                         buffer.append(symbols.getInternationalCurrencySymbol());
3327                     } else {
3328                         buffer.append(symbols.getCurrencySymbol());
3329                     }
3330                     continue;
3331                 case PATTERN_PERCENT:
3332                     c = symbols.getPercent();
3333                     break;
3334                 case PATTERN_PER_MILLE:
3335                     c = symbols.getPerMill();
3336                     break;
3337                 case PATTERN_MINUS:
3338                     c = symbols.getMinusSign();
3339                     break;
3340                 }
3341             }
3342             buffer.append(c);
3343         }
3344         return buffer.toString();
3345     }
3346 
3347     /**
3348      * Expand an affix pattern into an array of FieldPositions describing
3349      * how the pattern would be expanded.
3350      * All characters in the
3351      * pattern are literal unless prefixed by QUOTE.  The following characters
3352      * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
3353      * PATTERN_MINUS, and CURRENCY_SIGN.  If CURRENCY_SIGN is doubled (QUOTE +
3354      * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
3355      * currency code.  Any other character after a QUOTE represents itself.
3356      * QUOTE must be followed by another character; QUOTE may not occur by
3357      * itself at the end of the pattern.
3358      *
3359      * @param pattern the non-null, possibly empty pattern
3360      * @return FieldPosition array of the resulting fields.
3361      *
3362     private FieldPosition[] expandAffix(String pattern) {
3363         ArrayList<FieldPosition> positions = null;
3364         int stringIndex = 0;
3365         for (int i=0; i<pattern.length(); ) {
3366             char c = pattern.charAt(i++);
3367             if (c == QUOTE) {
3368                 int field = -1;
3369                 Format.Field fieldID = null;
3370                 c = pattern.charAt(i++);
3371                 switch (c) {
3372                 case CURRENCY_SIGN:
3373                     String string;
3374                     if (i<pattern.length() &&
3375                         pattern.charAt(i) == CURRENCY_SIGN) {
3376                         ++i;
3377                         string = symbols.getInternationalCurrencySymbol();
3378                     } else {
3379                         string = symbols.getCurrencySymbol();
3380                     }
3381                     if (!string.isEmpty()) {
3382                         if (positions == null) {
3383                             positions = new ArrayList<>(2);
3384                         }
3385                         FieldPosition fp = new FieldPosition(Field.CURRENCY);
3386                         fp.setBeginIndex(stringIndex);
3387                         fp.setEndIndex(stringIndex + string.length());
3388                         positions.add(fp);
3389                         stringIndex += string.length();
3390                     }
3391                     continue;
3392                 case PATTERN_PERCENT:
3393                     c = symbols.getPercent();
3394                     field = -1;
3395                     fieldID = Field.PERCENT;
3396                     break;
3397                 case PATTERN_PER_MILLE:
3398                     c = symbols.getPerMill();
3399                     field = -1;
3400                     fieldID = Field.PERMILLE;
3401                     break;
3402                 case PATTERN_MINUS:
3403                     c = symbols.getMinusSign();
3404                     field = -1;
3405                     fieldID = Field.SIGN;
3406                     break;
3407                 }
3408                 if (fieldID != null) {
3409                     if (positions == null) {
3410                         positions = new ArrayList<>(2);
3411                     }
3412                     FieldPosition fp = new FieldPosition(fieldID, field);
3413                     fp.setBeginIndex(stringIndex);
3414                     fp.setEndIndex(stringIndex + 1);
3415                     positions.add(fp);
3416                 }
3417             }
3418             stringIndex++;
3419         }
3420         if (positions != null) {
3421             return positions.toArray(EmptyFieldPositionArray);
3422         }
3423         return EmptyFieldPositionArray;
3424     }
3425 
3426     /**
3427      * Appends an affix pattern to the given StringBuffer, quoting special
3428      * characters as needed.  Uses the internal affix pattern, if that exists,
3429      * or the literal affix, if the internal affix pattern is null.  The
3430      * appended string will generate the same affix pattern (or literal affix)
3431      * when passed to toPattern().
3432      *
3433      * @param buffer the affix string is appended to this
3434      * @param affixPattern a pattern such as posPrefixPattern; may be null
3435      * @param expAffix a corresponding expanded affix, such as positivePrefix.
3436      * Ignored unless affixPattern is null.  If affixPattern is null, then
3437      * expAffix is appended as a literal affix.
3438      * @param localized true if the appended pattern should contain localized
3439      * pattern characters; otherwise, non-localized pattern chars are appended
3440      *
3441     private void appendAffix(StringBuffer buffer, String affixPattern,
3442                              String expAffix, boolean localized) {
3443         if (affixPattern == null) {
3444             appendAffix(buffer, expAffix, localized);
3445         } else {
3446             int i;
3447             for (int pos=0; pos<affixPattern.length(); pos=i) {
3448                 i = affixPattern.indexOf(QUOTE, pos);
3449                 if (i < 0) {
3450                     appendAffix(buffer, affixPattern.substring(pos), localized);
3451                     break;
3452                 }
3453                 if (i > pos) {
3454                     appendAffix(buffer, affixPattern.substring(pos, i), localized);
3455                 }
3456                 char c = affixPattern.charAt(++i);
3457                 ++i;
3458                 if (c == QUOTE) {
3459                     buffer.append(c);
3460                     // Fall through and append another QUOTE below
3461                 } else if (c == CURRENCY_SIGN &&
3462                            i<affixPattern.length() &&
3463                            affixPattern.charAt(i) == CURRENCY_SIGN) {
3464                     ++i;
3465                     buffer.append(c);
3466                     // Fall through and append another CURRENCY_SIGN below
3467                 } else if (localized) {
3468                     switch (c) {
3469                     case PATTERN_PERCENT:
3470                         c = symbols.getPercent();
3471                         break;
3472                     case PATTERN_PER_MILLE:
3473                         c = symbols.getPerMill();
3474                         break;
3475                     case PATTERN_MINUS:
3476                         c = symbols.getMinusSign();
3477                         break;
3478                     }
3479                 }
3480                 buffer.append(c);
3481             }
3482         }
3483     }
3484 
3485     /**
3486      * Append an affix to the given StringBuffer, using quotes if
3487      * there are special characters.  Single quotes themselves must be
3488      * escaped in either case.
3489      *
3490     private void appendAffix(StringBuffer buffer, String affix, boolean localized) {
3491         boolean needQuote;
3492         if (localized) {
3493             needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
3494                 || affix.indexOf(symbols.getGroupingSeparator()) >= 0
3495                 || affix.indexOf(symbols.getDecimalSeparator()) >= 0
3496                 || affix.indexOf(symbols.getPercent()) >= 0
3497                 || affix.indexOf(symbols.getPerMill()) >= 0
3498                 || affix.indexOf(symbols.getDigit()) >= 0
3499                 || affix.indexOf(symbols.getPatternSeparator()) >= 0
3500                 || affix.indexOf(symbols.getMinusSign()) >= 0
3501                 || affix.indexOf(CURRENCY_SIGN) >= 0;
3502         } else {
3503             needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
3504                 || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
3505                 || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
3506                 || affix.indexOf(PATTERN_PERCENT) >= 0
3507                 || affix.indexOf(PATTERN_PER_MILLE) >= 0
3508                 || affix.indexOf(PATTERN_DIGIT) >= 0
3509                 || affix.indexOf(PATTERN_SEPARATOR) >= 0
3510                 || affix.indexOf(PATTERN_MINUS) >= 0
3511                 || affix.indexOf(CURRENCY_SIGN) >= 0;
3512         }
3513         if (needQuote) buffer.append('\'');
3514         if (affix.indexOf('\'') < 0) buffer.append(affix);
3515         else {
3516             for (int j=0; j<affix.length(); ++j) {
3517                 char c = affix.charAt(j);
3518                 buffer.append(c);
3519                 if (c == '\'') buffer.append(c);
3520             }
3521         }
3522         if (needQuote) buffer.append('\'');
3523     }
3524 
3525     /**
3526      * Does the real work of generating a pattern.  *
3527     private String toPattern(boolean localized) {
3528         StringBuffer result = new StringBuffer();
3529         for (int j = 1; j >= 0; --j) {
3530             if (j == 1)
3531                 appendAffix(result, posPrefixPattern, positivePrefix, localized);
3532             else appendAffix(result, negPrefixPattern, negativePrefix, localized);
3533             int i;
3534             int digitCount = useExponentialNotation
3535                         ? getMaximumIntegerDigits()
3536                         : Math.max(groupingSize, getMinimumIntegerDigits())+1;
3537             for (i = digitCount; i > 0; --i) {
3538                 if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&
3539                     i % groupingSize == 0) {
3540                     result.append(localized ? symbols.getGroupingSeparator() :
3541                                   PATTERN_GROUPING_SEPARATOR);
3542                 }
3543                 result.append(i <= getMinimumIntegerDigits()
3544                     ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)
3545                     : (localized ? symbols.getDigit() : PATTERN_DIGIT));
3546             }
3547             if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)
3548                 result.append(localized ? symbols.getDecimalSeparator() :
3549                               PATTERN_DECIMAL_SEPARATOR);
3550             for (i = 0; i < getMaximumFractionDigits(); ++i) {
3551                 if (i < getMinimumFractionDigits()) {
3552                     result.append(localized ? symbols.getZeroDigit() :
3553                                   PATTERN_ZERO_DIGIT);
3554                 } else {
3555                     result.append(localized ? symbols.getDigit() :
3556                                   PATTERN_DIGIT);
3557                 }
3558             }
3559         if (useExponentialNotation)
3560         {
3561             result.append(localized ? symbols.getExponentSeparator() :
3562                   PATTERN_EXPONENT);
3563         for (i=0; i<minExponentDigits; ++i)
3564                     result.append(localized ? symbols.getZeroDigit() :
3565                                   PATTERN_ZERO_DIGIT);
3566         }
3567             if (j == 1) {
3568                 appendAffix(result, posSuffixPattern, positiveSuffix, localized);
3569                 if ((negSuffixPattern == posSuffixPattern && // n == p == null
3570                      negativeSuffix.equals(positiveSuffix))
3571                     || (negSuffixPattern != null &&
3572                         negSuffixPattern.equals(posSuffixPattern))) {
3573                     if ((negPrefixPattern != null && posPrefixPattern != null &&
3574                          negPrefixPattern.equals("'-" + posPrefixPattern)) ||
3575                         (negPrefixPattern == posPrefixPattern && // n == p == null
3576                          negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
3577                         break;
3578                 }
3579                 result.append(localized ? symbols.getPatternSeparator() :
3580                               PATTERN_SEPARATOR);
3581             } else appendAffix(result, negSuffixPattern, negativeSuffix, localized);
3582         }
3583         return result.toString();
3584     }
3585     */
3586     // END Android-removed: Unused private helpers.
3587 
3588     /**
3589      * Apply the given pattern to this Format object.  A pattern is a
3590      * short-hand specification for the various formatting properties.
3591      * These properties can also be changed individually through the
3592      * various setter methods.
3593      * <p>
3594      * There is no limit to integer digits set
3595      * by this routine, since that is the typical end-user desire;
3596      * use setMaximumInteger if you want to set a real value.
3597      * For negative numbers, use a second pattern, separated by a semicolon
3598      * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
3599      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
3600      * a maximum of 2 fraction digits.
3601      * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
3602      * parentheses.
3603      * <p>In negative patterns, the minimum and maximum counts are ignored;
3604      * these are presumed to be set in the positive pattern.
3605      *
3606      * @param pattern a new pattern
3607      * @exception NullPointerException if <code>pattern</code> is null
3608      * @exception IllegalArgumentException if the given pattern is invalid.
3609      */
applyPattern(String pattern)3610     public void applyPattern(String pattern) {
3611         // Android-changed: use ICU.
3612         // applyPattern(pattern, false);
3613         icuDecimalFormat.applyPattern(pattern);
3614         updateFieldsFromIcu();
3615     }
3616 
3617     /**
3618      * Apply the given pattern to this Format object.  The pattern
3619      * is assumed to be in a localized notation. A pattern is a
3620      * short-hand specification for the various formatting properties.
3621      * These properties can also be changed individually through the
3622      * various setter methods.
3623      * <p>
3624      * There is no limit to integer digits set
3625      * by this routine, since that is the typical end-user desire;
3626      * use setMaximumInteger if you want to set a real value.
3627      * For negative numbers, use a second pattern, separated by a semicolon
3628      * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
3629      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
3630      * a maximum of 2 fraction digits.
3631      * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
3632      * parentheses.
3633      * <p>In negative patterns, the minimum and maximum counts are ignored;
3634      * these are presumed to be set in the positive pattern.
3635      *
3636      * @param pattern a new pattern
3637      * @exception NullPointerException if <code>pattern</code> is null
3638      * @exception IllegalArgumentException if the given pattern is invalid.
3639      */
applyLocalizedPattern(String pattern)3640     public void applyLocalizedPattern(String pattern) {
3641         // Android-changed: use ICU.
3642         // applyPattern(pattern, true);
3643         icuDecimalFormat.applyLocalizedPattern(pattern);
3644         updateFieldsFromIcu();
3645     }
3646 
3647     // BEGIN Android-removed: applyPattern(String, boolean) as apply[Localized]Pattern calls ICU directly.
3648     /*
3649     /**
3650      * Does the real work of applying a pattern.
3651      *
3652     private void applyPattern(String pattern, boolean localized) {
3653         char zeroDigit         = PATTERN_ZERO_DIGIT;
3654         char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
3655         char decimalSeparator  = PATTERN_DECIMAL_SEPARATOR;
3656         char percent           = PATTERN_PERCENT;
3657         char perMill           = PATTERN_PER_MILLE;
3658         char digit             = PATTERN_DIGIT;
3659         char separator         = PATTERN_SEPARATOR;
3660         String exponent          = PATTERN_EXPONENT;
3661         char minus             = PATTERN_MINUS;
3662         if (localized) {
3663             zeroDigit         = symbols.getZeroDigit();
3664             groupingSeparator = symbols.getGroupingSeparator();
3665             decimalSeparator  = symbols.getDecimalSeparator();
3666             percent           = symbols.getPercent();
3667             perMill           = symbols.getPerMill();
3668             digit             = symbols.getDigit();
3669             separator         = symbols.getPatternSeparator();
3670             exponent          = symbols.getExponentSeparator();
3671             minus             = symbols.getMinusSign();
3672         }
3673         boolean gotNegative = false;
3674         decimalSeparatorAlwaysShown = false;
3675         isCurrencyFormat = false;
3676         useExponentialNotation = false;
3677 
3678         int start = 0;
3679         for (int j = 1; j >= 0 && start < pattern.length(); --j) {
3680             boolean inQuote = false;
3681             StringBuffer prefix = new StringBuffer();
3682             StringBuffer suffix = new StringBuffer();
3683             int decimalPos = -1;
3684             int multiplier = 1;
3685             int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
3686             byte groupingCount = -1;
3687 
3688             // The phase ranges from 0 to 2.  Phase 0 is the prefix.  Phase 1 is
3689             // the section of the pattern with digits, decimal separator,
3690             // grouping characters.  Phase 2 is the suffix.  In phases 0 and 2,
3691             // percent, per mille, and currency symbols are recognized and
3692             // translated.  The separation of the characters into phases is
3693             // strictly enforced; if phase 1 characters are to appear in the
3694             // suffix, for example, they must be quoted.
3695             int phase = 0;
3696 
3697             // The affix is either the prefix or the suffix.
3698             StringBuffer affix = prefix;
3699 
3700             for (int pos = start; pos < pattern.length(); ++pos) {
3701                 char ch = pattern.charAt(pos);
3702                 switch (phase) {
3703                 case 0:
3704                 case 2:
3705                     // Process the prefix / suffix characters
3706                     if (inQuote) {
3707                         // A quote within quotes indicates either the closing
3708                         // quote or two quotes, which is a quote literal. That
3709                         // is, we have the second quote in 'do' or 'don''t'.
3710                         if (ch == QUOTE) {
3711                             if ((pos+1) < pattern.length() &&
3712                                 pattern.charAt(pos+1) == QUOTE) {
3713                                 ++pos;
3714                                 affix.append("''"); // 'don''t'
3715                             } else {
3716                                 inQuote = false; // 'do'
3717                             }
3718                             continue;
3719                         }
3720                     } else {
3721                         // Process unquoted characters seen in prefix or suffix
3722                         // phase.
3723                         if (ch == digit ||
3724                             ch == zeroDigit ||
3725                             ch == groupingSeparator ||
3726                             ch == decimalSeparator) {
3727                             phase = 1;
3728                             --pos; // Reprocess this character
3729                             continue;
3730                         } else if (ch == CURRENCY_SIGN) {
3731                             // Use lookahead to determine if the currency sign
3732                             // is doubled or not.
3733                             boolean doubled = (pos + 1) < pattern.length() &&
3734                                 pattern.charAt(pos + 1) == CURRENCY_SIGN;
3735                             if (doubled) { // Skip over the doubled character
3736                              ++pos;
3737                             }
3738                             isCurrencyFormat = true;
3739                             affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");
3740                             continue;
3741                         } else if (ch == QUOTE) {
3742                             // A quote outside quotes indicates either the
3743                             // opening quote or two quotes, which is a quote
3744                             // literal. That is, we have the first quote in 'do'
3745                             // or o''clock.
3746                             if (ch == QUOTE) {
3747                                 if ((pos+1) < pattern.length() &&
3748                                     pattern.charAt(pos+1) == QUOTE) {
3749                                     ++pos;
3750                                     affix.append("''"); // o''clock
3751                                 } else {
3752                                     inQuote = true; // 'do'
3753                                 }
3754                                 continue;
3755                             }
3756                         } else if (ch == separator) {
3757                             // Don't allow separators before we see digit
3758                             // characters of phase 1, and don't allow separators
3759                             // in the second pattern (j == 0).
3760                             if (phase == 0 || j == 0) {
3761                                 throw new IllegalArgumentException("Unquoted special character '" +
3762                                     ch + "' in pattern \"" + pattern + '"');
3763                             }
3764                             start = pos + 1;
3765                             pos = pattern.length();
3766                             continue;
3767                         }
3768 
3769                         // Next handle characters which are appended directly.
3770                         else if (ch == percent) {
3771                             if (multiplier != 1) {
3772                                 throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
3773                                     pattern + '"');
3774                             }
3775                             multiplier = 100;
3776                             affix.append("'%");
3777                             continue;
3778                         } else if (ch == perMill) {
3779                             if (multiplier != 1) {
3780                                 throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
3781                                     pattern + '"');
3782                             }
3783                             multiplier = 1000;
3784                             affix.append("'\u2030");
3785                             continue;
3786                         } else if (ch == minus) {
3787                             affix.append("'-");
3788                             continue;
3789                         }
3790                     }
3791                     // Note that if we are within quotes, or if this is an
3792                     // unquoted, non-special character, then we usually fall
3793                     // through to here.
3794                     affix.append(ch);
3795                     break;
3796 
3797                 case 1:
3798                     // The negative subpattern (j = 0) serves only to specify the
3799                     // negative prefix and suffix, so all the phase 1 characters
3800                     // e.g. digits, zeroDigit, groupingSeparator,
3801                     // decimalSeparator, exponent are ignored
3802                     if (j == 0) {
3803                         while (pos < pattern.length()) {
3804                             char negPatternChar = pattern.charAt(pos);
3805                             if (negPatternChar == digit
3806                                     || negPatternChar == zeroDigit
3807                                     || negPatternChar == groupingSeparator
3808                                     || negPatternChar == decimalSeparator) {
3809                                 ++pos;
3810                             } else if (pattern.regionMatches(pos, exponent,
3811                                     0, exponent.length())) {
3812                                 pos = pos + exponent.length();
3813                             } else {
3814                                 // Not a phase 1 character, consider it as
3815                                 // suffix and parse it in phase 2
3816                                 --pos; //process it again in outer loop
3817                                 phase = 2;
3818                                 affix = suffix;
3819                                 break;
3820                             }
3821                         }
3822                         continue;
3823                     }
3824 
3825                     // Process the digits, decimal, and grouping characters. We
3826                     // record five pieces of information. We expect the digits
3827                     // to occur in the pattern ####0000.####, and we record the
3828                     // number of left digits, zero (central) digits, and right
3829                     // digits. The position of the last grouping character is
3830                     // recorded (should be somewhere within the first two blocks
3831                     // of characters), as is the position of the decimal point,
3832                     // if any (should be in the zero digits). If there is no
3833                     // decimal point, then there should be no right digits.
3834                     if (ch == digit) {
3835                         if (zeroDigitCount > 0) {
3836                             ++digitRightCount;
3837                         } else {
3838                             ++digitLeftCount;
3839                         }
3840                         if (groupingCount >= 0 && decimalPos < 0) {
3841                             ++groupingCount;
3842                         }
3843                     } else if (ch == zeroDigit) {
3844                         if (digitRightCount > 0) {
3845                             throw new IllegalArgumentException("Unexpected '0' in pattern \"" +
3846                                 pattern + '"');
3847                         }
3848                         ++zeroDigitCount;
3849                         if (groupingCount >= 0 && decimalPos < 0) {
3850                             ++groupingCount;
3851                         }
3852                     } else if (ch == groupingSeparator) {
3853                         groupingCount = 0;
3854                     } else if (ch == decimalSeparator) {
3855                         if (decimalPos >= 0) {
3856                             throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +
3857                                 pattern + '"');
3858                         }
3859                         decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
3860                     } else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){
3861                         if (useExponentialNotation) {
3862                             throw new IllegalArgumentException("Multiple exponential " +
3863                                 "symbols in pattern \"" + pattern + '"');
3864                         }
3865                         useExponentialNotation = true;
3866                         minExponentDigits = 0;
3867 
3868                         // Use lookahead to parse out the exponential part
3869                         // of the pattern, then jump into phase 2.
3870                         pos = pos+exponent.length();
3871                          while (pos < pattern.length() &&
3872                                pattern.charAt(pos) == zeroDigit) {
3873                             ++minExponentDigits;
3874                             ++pos;
3875                         }
3876 
3877                         if ((digitLeftCount + zeroDigitCount) < 1 ||
3878                             minExponentDigits < 1) {
3879                             throw new IllegalArgumentException("Malformed exponential " +
3880                                 "pattern \"" + pattern + '"');
3881                         }
3882 
3883                         // Transition to phase 2
3884                         phase = 2;
3885                         affix = suffix;
3886                         --pos;
3887                         continue;
3888                     } else {
3889                         phase = 2;
3890                         affix = suffix;
3891                         --pos;
3892                         continue;
3893                     }
3894                     break;
3895                 }
3896             }
3897 
3898             // Handle patterns with no '0' pattern character. These patterns
3899             // are legal, but must be interpreted.  "##.###" -> "#0.###".
3900             // ".###" -> ".0##".
3901             /* We allow patterns of the form "####" to produce a zeroDigitCount
3902              * of zero (got that?); although this seems like it might make it
3903              * possible for format() to produce empty strings, format() checks
3904              * for this condition and outputs a zero digit in this situation.
3905              * Having a zeroDigitCount of zero yields a minimum integer digits
3906              * of zero, which allows proper round-trip patterns.  That is, we
3907              * don't want "#" to become "#0" when toPattern() is called (even
3908              * though that's what it really is, semantically).
3909              *
3910             if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
3911                 // Handle "###.###" and "###." and ".###"
3912                 int n = decimalPos;
3913                 if (n == 0) { // Handle ".###"
3914                     ++n;
3915                 }
3916                 digitRightCount = digitLeftCount - n;
3917                 digitLeftCount = n - 1;
3918                 zeroDigitCount = 1;
3919             }
3920 
3921             // Do syntax checking on the digits.
3922             if ((decimalPos < 0 && digitRightCount > 0) ||
3923                 (decimalPos >= 0 && (decimalPos < digitLeftCount ||
3924                  decimalPos > (digitLeftCount + zeroDigitCount))) ||
3925                  groupingCount == 0 || inQuote) {
3926                 throw new IllegalArgumentException("Malformed pattern \"" +
3927                     pattern + '"');
3928             }
3929 
3930             if (j == 1) {
3931                 posPrefixPattern = prefix.toString();
3932                 posSuffixPattern = suffix.toString();
3933                 negPrefixPattern = posPrefixPattern;   // assume these for now
3934                 negSuffixPattern = posSuffixPattern;
3935                 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
3936                 /* The effectiveDecimalPos is the position the decimal is at or
3937                  * would be at if there is no decimal. Note that if decimalPos<0,
3938                  * then digitTotalCount == digitLeftCount + zeroDigitCount.
3939                  *
3940                 int effectiveDecimalPos = decimalPos >= 0 ?
3941                     decimalPos : digitTotalCount;
3942                 setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);
3943                 setMaximumIntegerDigits(useExponentialNotation ?
3944                     digitLeftCount + getMinimumIntegerDigits() :
3945                     MAXIMUM_INTEGER_DIGITS);
3946                 setMaximumFractionDigits(decimalPos >= 0 ?
3947                     (digitTotalCount - decimalPos) : 0);
3948                 setMinimumFractionDigits(decimalPos >= 0 ?
3949                     (digitLeftCount + zeroDigitCount - decimalPos) : 0);
3950                 setGroupingUsed(groupingCount > 0);
3951                 this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
3952                 this.multiplier = multiplier;
3953                 setDecimalSeparatorAlwaysShown(decimalPos == 0 ||
3954                     decimalPos == digitTotalCount);
3955             } else {
3956                 negPrefixPattern = prefix.toString();
3957                 negSuffixPattern = suffix.toString();
3958                 gotNegative = true;
3959             }
3960         }
3961 
3962         if (pattern.isEmpty()) {
3963             posPrefixPattern = posSuffixPattern = "";
3964             setMinimumIntegerDigits(0);
3965             setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
3966             setMinimumFractionDigits(0);
3967             setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
3968         }
3969 
3970         // If there was no negative pattern, or if the negative pattern is
3971         // identical to the positive pattern, then prepend the minus sign to
3972         // the positive pattern to form the negative pattern.
3973         if (!gotNegative ||
3974             (negPrefixPattern.equals(posPrefixPattern)
3975              && negSuffixPattern.equals(posSuffixPattern))) {
3976             negSuffixPattern = posSuffixPattern;
3977             negPrefixPattern = "'-" + posPrefixPattern;
3978         }
3979 
3980         expandAffixes();
3981     }
3982     */
3983     // END Android-removed: applyPattern(String, boolean) as apply[Localized]Pattern calls ICU directly.
3984 
3985     /**
3986      * Sets the maximum number of digits allowed in the integer portion of a
3987      * number.
3988      * For formatting numbers other than <code>BigInteger</code> and
3989      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
3990      * 309 is used. Negative input values are replaced with 0.
3991      * @see NumberFormat#setMaximumIntegerDigits
3992      */
3993     @Override
setMaximumIntegerDigits(int newValue)3994     public void setMaximumIntegerDigits(int newValue) {
3995         maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
3996         super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
3997             DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
3998         if (minimumIntegerDigits > maximumIntegerDigits) {
3999             minimumIntegerDigits = maximumIntegerDigits;
4000             super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
4001                 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
4002         }
4003         // Android-added: use ICU.
4004         icuDecimalFormat.setMaximumIntegerDigits(getMaximumIntegerDigits());
4005         // Android-removed: fast path related code.
4006         // fastPathCheckNeeded = true;
4007     }
4008 
4009     /**
4010      * Sets the minimum number of digits allowed in the integer portion of a
4011      * number.
4012      * For formatting numbers other than <code>BigInteger</code> and
4013      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
4014      * 309 is used. Negative input values are replaced with 0.
4015      * @see NumberFormat#setMinimumIntegerDigits
4016      */
4017     @Override
setMinimumIntegerDigits(int newValue)4018     public void setMinimumIntegerDigits(int newValue) {
4019         minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
4020         super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
4021             DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
4022         if (minimumIntegerDigits > maximumIntegerDigits) {
4023             maximumIntegerDigits = minimumIntegerDigits;
4024             super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
4025                 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
4026         }
4027         // Android-added: use ICU.
4028         icuDecimalFormat.setMinimumIntegerDigits(getMinimumIntegerDigits());
4029         // Android-removed: fast path related code.
4030         // fastPathCheckNeeded = true;
4031     }
4032 
4033     /**
4034      * Sets the maximum number of digits allowed in the fraction portion of a
4035      * number.
4036      * For formatting numbers other than <code>BigInteger</code> and
4037      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
4038      * 340 is used. Negative input values are replaced with 0.
4039      * @see NumberFormat#setMaximumFractionDigits
4040      */
4041     @Override
setMaximumFractionDigits(int newValue)4042     public void setMaximumFractionDigits(int newValue) {
4043         maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
4044         super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
4045             DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
4046         if (minimumFractionDigits > maximumFractionDigits) {
4047             minimumFractionDigits = maximumFractionDigits;
4048             super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
4049                 DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
4050         }
4051         // Android-added: use ICU.
4052         icuDecimalFormat.setMaximumFractionDigits(getMaximumFractionDigits());
4053         // Android-removed: fast path related code.
4054         // fastPathCheckNeeded = true;
4055     }
4056 
4057     /**
4058      * Sets the minimum number of digits allowed in the fraction portion of a
4059      * number.
4060      * For formatting numbers other than <code>BigInteger</code> and
4061      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
4062      * 340 is used. Negative input values are replaced with 0.
4063      * @see NumberFormat#setMinimumFractionDigits
4064      */
4065     @Override
setMinimumFractionDigits(int newValue)4066     public void setMinimumFractionDigits(int newValue) {
4067         minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
4068         super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
4069             DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
4070         if (minimumFractionDigits > maximumFractionDigits) {
4071             maximumFractionDigits = minimumFractionDigits;
4072             super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
4073                 DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
4074         }
4075         // Android-added: use ICU.
4076         icuDecimalFormat.setMinimumFractionDigits(getMinimumFractionDigits());
4077         // Android-removed: fast path related code.
4078         // fastPathCheckNeeded = true;
4079     }
4080 
4081     /**
4082      * Gets the maximum number of digits allowed in the integer portion of a
4083      * number.
4084      * For formatting numbers other than <code>BigInteger</code> and
4085      * <code>BigDecimal</code> objects, the lower of the return value and
4086      * 309 is used.
4087      * @see #setMaximumIntegerDigits
4088      */
4089     @Override
getMaximumIntegerDigits()4090     public int getMaximumIntegerDigits() {
4091         return maximumIntegerDigits;
4092     }
4093 
4094     /**
4095      * Gets the minimum number of digits allowed in the integer portion of a
4096      * number.
4097      * For formatting numbers other than <code>BigInteger</code> and
4098      * <code>BigDecimal</code> objects, the lower of the return value and
4099      * 309 is used.
4100      * @see #setMinimumIntegerDigits
4101      */
4102     @Override
getMinimumIntegerDigits()4103     public int getMinimumIntegerDigits() {
4104         return minimumIntegerDigits;
4105     }
4106 
4107     /**
4108      * Gets the maximum number of digits allowed in the fraction portion of a
4109      * number.
4110      * For formatting numbers other than <code>BigInteger</code> and
4111      * <code>BigDecimal</code> objects, the lower of the return value and
4112      * 340 is used.
4113      * @see #setMaximumFractionDigits
4114      */
4115     @Override
getMaximumFractionDigits()4116     public int getMaximumFractionDigits() {
4117         return maximumFractionDigits;
4118     }
4119 
4120     /**
4121      * Gets the minimum number of digits allowed in the fraction portion of a
4122      * number.
4123      * For formatting numbers other than <code>BigInteger</code> and
4124      * <code>BigDecimal</code> objects, the lower of the return value and
4125      * 340 is used.
4126      * @see #setMinimumFractionDigits
4127      */
4128     @Override
getMinimumFractionDigits()4129     public int getMinimumFractionDigits() {
4130         return minimumFractionDigits;
4131     }
4132 
4133     /**
4134      * Gets the currency used by this decimal format when formatting
4135      * currency values.
4136      * The currency is obtained by calling
4137      * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
4138      * on this number format's symbols.
4139      *
4140      * @return the currency used by this decimal format, or <code>null</code>
4141      * @since 1.4
4142      */
4143     @Override
getCurrency()4144     public Currency getCurrency() {
4145         return symbols.getCurrency();
4146     }
4147 
4148     /**
4149      * Sets the currency used by this number format when formatting
4150      * currency values. This does not update the minimum or maximum
4151      * number of fraction digits used by the number format.
4152      * The currency is set by calling
4153      * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
4154      * on this number format's symbols.
4155      *
4156      * @param currency the new currency to be used by this decimal format
4157      * @exception NullPointerException if <code>currency</code> is null
4158      * @since 1.4
4159      */
4160     @Override
setCurrency(Currency currency)4161     public void setCurrency(Currency currency) {
4162         // BEGIN Android-changed: use ICU.
4163         // Set the international currency symbol, and currency symbol on the DecimalFormatSymbols
4164         // object and tell ICU to use that.
4165         /*
4166         if (currency != symbols.getCurrency()) {
4167             symbols.setCurrency(currency);
4168             if (isCurrencyFormat) {
4169                 expandAffixes();
4170             }
4171         }
4172         */
4173         if (currency != symbols.getCurrency()
4174             || !currency.getSymbol().equals(symbols.getCurrencySymbol())) {
4175             symbols.setCurrency(currency);
4176             icuDecimalFormat.setDecimalFormatSymbols(symbols.getIcuDecimalFormatSymbols());
4177             // Giving the icuDecimalFormat a new currency will cause the fractional digits to be
4178             // updated. This class is specified to not touch the fraction digits, so we re-set them.
4179             icuDecimalFormat.setMinimumFractionDigits(minimumFractionDigits);
4180             icuDecimalFormat.setMaximumFractionDigits(maximumFractionDigits);
4181         }
4182         // END Android-changed: use ICU.
4183         // Android-removed: fast path related code.
4184         // fastPathCheckNeeded = true;
4185     }
4186 
4187     /**
4188      * Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
4189      *
4190      * @return The <code>RoundingMode</code> used for this DecimalFormat.
4191      * @see #setRoundingMode(RoundingMode)
4192      * @since 1.6
4193      */
4194     @Override
getRoundingMode()4195     public RoundingMode getRoundingMode() {
4196         return roundingMode;
4197     }
4198 
4199     // BEGIN Android-added: convertRoundingMode() to convert between Java and ICU RoundingMode enums.
convertRoundingMode(RoundingMode rm)4200     private static int convertRoundingMode(RoundingMode rm) {
4201         switch (rm) {
4202         case UP:
4203             return MathContext.ROUND_UP;
4204         case DOWN:
4205             return MathContext.ROUND_DOWN;
4206         case CEILING:
4207             return MathContext.ROUND_CEILING;
4208         case FLOOR:
4209             return MathContext.ROUND_FLOOR;
4210         case HALF_UP:
4211             return MathContext.ROUND_HALF_UP;
4212         case HALF_DOWN:
4213             return MathContext.ROUND_HALF_DOWN;
4214         case HALF_EVEN:
4215             return MathContext.ROUND_HALF_EVEN;
4216         case UNNECESSARY:
4217             return MathContext.ROUND_UNNECESSARY;
4218         }
4219         throw new IllegalArgumentException("Invalid rounding mode specified");
4220     }
4221     // END Android-added: convertRoundingMode() to convert between Java and ICU RoundingMode enums.
4222 
4223     /**
4224      * Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
4225      *
4226      * @param roundingMode The <code>RoundingMode</code> to be used
4227      * @see #getRoundingMode()
4228      * @exception NullPointerException if <code>roundingMode</code> is null.
4229      * @since 1.6
4230      */
4231     @Override
setRoundingMode(RoundingMode roundingMode)4232     public void setRoundingMode(RoundingMode roundingMode) {
4233         if (roundingMode == null) {
4234             throw new NullPointerException();
4235         }
4236 
4237         this.roundingMode = roundingMode;
4238         // Android-changed: use ICU.
4239         // digitList.setRoundingMode(roundingMode);
4240         icuDecimalFormat.setRoundingMode(convertRoundingMode(roundingMode));
4241         // Android-removed: fast path related code.
4242         // fastPathCheckNeeded = true;
4243     }
4244 
4245     // BEGIN Android-added: Upstream code from OpenJDK 7u40 release.
4246     // This method was removed in OpenJDK 8 in favor of doing equivalent work in the provider. Since
4247     // Android removed support for providers for NumberFormat we keep this method around as an
4248     // "Android addition".
4249     /**
4250      * Adjusts the minimum and maximum fraction digits to values that
4251      * are reasonable for the currency's default fraction digits.
4252      */
adjustForCurrencyDefaultFractionDigits()4253     void adjustForCurrencyDefaultFractionDigits() {
4254         Currency currency = symbols.getCurrency();
4255         if (currency == null) {
4256             try {
4257                 currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
4258             } catch (IllegalArgumentException e) {
4259             }
4260         }
4261         if (currency != null) {
4262             int digits = currency.getDefaultFractionDigits();
4263             if (digits != -1) {
4264                 int oldMinDigits = getMinimumFractionDigits();
4265                 // Common patterns are "#.##", "#.00", "#".
4266                 // Try to adjust all of them in a reasonable way.
4267                 if (oldMinDigits == getMaximumFractionDigits()) {
4268                     setMinimumFractionDigits(digits);
4269                     setMaximumFractionDigits(digits);
4270                 } else {
4271                     setMinimumFractionDigits(Math.min(digits, oldMinDigits));
4272                     setMaximumFractionDigits(digits);
4273                 }
4274             }
4275         }
4276     }
4277     // END Android-added: Upstream code from OpenJDK 7u40 release.
4278 
4279     // BEGIN Android-added: Custom serialization code for compatibility with RI serialization.
4280     // the fields list to be serialized
4281     private static final ObjectStreamField[] serialPersistentFields = {
4282             new ObjectStreamField("positivePrefix", String.class),
4283             new ObjectStreamField("positiveSuffix", String.class),
4284             new ObjectStreamField("negativePrefix", String.class),
4285             new ObjectStreamField("negativeSuffix", String.class),
4286             new ObjectStreamField("posPrefixPattern", String.class),
4287             new ObjectStreamField("posSuffixPattern", String.class),
4288             new ObjectStreamField("negPrefixPattern", String.class),
4289             new ObjectStreamField("negSuffixPattern", String.class),
4290             new ObjectStreamField("multiplier", int.class),
4291             new ObjectStreamField("groupingSize", byte.class),
4292             new ObjectStreamField("groupingUsed", boolean.class),
4293             new ObjectStreamField("decimalSeparatorAlwaysShown", boolean.class),
4294             new ObjectStreamField("parseBigDecimal", boolean.class),
4295             new ObjectStreamField("roundingMode", RoundingMode.class),
4296             new ObjectStreamField("symbols", DecimalFormatSymbols.class),
4297             new ObjectStreamField("useExponentialNotation", boolean.class),
4298             new ObjectStreamField("minExponentDigits", byte.class),
4299             new ObjectStreamField("maximumIntegerDigits", int.class),
4300             new ObjectStreamField("minimumIntegerDigits", int.class),
4301             new ObjectStreamField("maximumFractionDigits", int.class),
4302             new ObjectStreamField("minimumFractionDigits", int.class),
4303             new ObjectStreamField("serialVersionOnStream", int.class),
4304     };
4305 
writeObject(ObjectOutputStream stream)4306     private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException {
4307         ObjectOutputStream.PutField fields = stream.putFields();
4308         fields.put("positivePrefix", icuDecimalFormat.getPositivePrefix());
4309         fields.put("positiveSuffix", icuDecimalFormat.getPositiveSuffix());
4310         fields.put("negativePrefix", icuDecimalFormat.getNegativePrefix());
4311         fields.put("negativeSuffix", icuDecimalFormat.getNegativeSuffix());
4312         fields.put("posPrefixPattern", (String) null);
4313         fields.put("posSuffixPattern", (String) null);
4314         fields.put("negPrefixPattern", (String) null);
4315         fields.put("negSuffixPattern", (String) null);
4316         fields.put("multiplier", icuDecimalFormat.getMultiplier());
4317         fields.put("groupingSize", (byte) icuDecimalFormat.getGroupingSize());
4318         fields.put("groupingUsed", icuDecimalFormat.isGroupingUsed());
4319         fields.put("decimalSeparatorAlwaysShown", icuDecimalFormat.isDecimalSeparatorAlwaysShown());
4320         fields.put("parseBigDecimal", icuDecimalFormat.isParseBigDecimal());
4321         fields.put("roundingMode", roundingMode);
4322         fields.put("symbols", symbols);
4323         fields.put("useExponentialNotation", false);
4324         fields.put("minExponentDigits", (byte) 0);
4325         fields.put("maximumIntegerDigits", icuDecimalFormat.getMaximumIntegerDigits());
4326         fields.put("minimumIntegerDigits", icuDecimalFormat.getMinimumIntegerDigits());
4327         fields.put("maximumFractionDigits", icuDecimalFormat.getMaximumFractionDigits());
4328         fields.put("minimumFractionDigits", icuDecimalFormat.getMinimumFractionDigits());
4329         fields.put("serialVersionOnStream", currentSerialVersion);
4330         stream.writeFields();
4331     }
4332     // END Android-added: Custom serialization code for compatibility with RI serialization.
4333 
4334     /**
4335      * Reads the default serializable fields from the stream and performs
4336      * validations and adjustments for older serialized versions. The
4337      * validations and adjustments are:
4338      * <ol>
4339      * <li>
4340      * Verify that the superclass's digit count fields correctly reflect
4341      * the limits imposed on formatting numbers other than
4342      * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
4343      * limits are stored in the superclass for serialization compatibility
4344      * with older versions, while the limits for <code>BigInteger</code> and
4345      * <code>BigDecimal</code> objects are kept in this class.
4346      * If, in the superclass, the minimum or maximum integer digit count is
4347      * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
4348      * maximum fraction digit count is larger than
4349      * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
4350      * and this method throws an <code>InvalidObjectException</code>.
4351      * <li>
4352      * If <code>serialVersionOnStream</code> is less than 4, initialize
4353      * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
4354      * RoundingMode.HALF_EVEN}.  This field is new with version 4.
4355      * <li>
4356      * If <code>serialVersionOnStream</code> is less than 3, then call
4357      * the setters for the minimum and maximum integer and fraction digits with
4358      * the values of the corresponding superclass getters to initialize the
4359      * fields in this class. The fields in this class are new with version 3.
4360      * <li>
4361      * If <code>serialVersionOnStream</code> is less than 1, indicating that
4362      * the stream was written by JDK 1.1, initialize
4363      * <code>useExponentialNotation</code>
4364      * to false, since it was not present in JDK 1.1.
4365      * <li>
4366      * Set <code>serialVersionOnStream</code> to the maximum allowed value so
4367      * that default serialization will work properly if this object is streamed
4368      * out again.
4369      * </ol>
4370      *
4371      * <p>Stream versions older than 2 will not have the affix pattern variables
4372      * <code>posPrefixPattern</code> etc.  As a result, they will be initialized
4373      * to <code>null</code>, which means the affix strings will be taken as
4374      * literal values.  This is exactly what we want, since that corresponds to
4375      * the pre-version-2 behavior.
4376      */
readObject(ObjectInputStream stream)4377     private void readObject(ObjectInputStream stream)
4378          throws IOException, ClassNotFoundException {
4379         // BEGIN Android-changed: Custom serialization code for compatibility with RI serialization.
4380         /*
4381         stream.defaultReadObject();
4382         digitList = new DigitList();
4383 
4384         // We force complete fast-path reinitialization when the instance is
4385         // deserialized. See clone() comment on fastPathCheckNeeded.
4386         fastPathCheckNeeded = true;
4387         isFastPath = false;
4388         fastPathData = null;
4389 
4390         if (serialVersionOnStream < 4) {
4391             setRoundingMode(RoundingMode.HALF_EVEN);
4392         } else {
4393             setRoundingMode(getRoundingMode());
4394         }
4395 
4396         // We only need to check the maximum counts because NumberFormat
4397         // .readObject has already ensured that the maximum is greater than the
4398         // minimum count.
4399         if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
4400             super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
4401             throw new InvalidObjectException("Digit count out of range");
4402         }
4403         if (serialVersionOnStream < 3) {
4404             setMaximumIntegerDigits(super.getMaximumIntegerDigits());
4405             setMinimumIntegerDigits(super.getMinimumIntegerDigits());
4406             setMaximumFractionDigits(super.getMaximumFractionDigits());
4407             setMinimumFractionDigits(super.getMinimumFractionDigits());
4408         }
4409         if (serialVersionOnStream < 1) {
4410             // Didn't have exponential fields
4411             useExponentialNotation = false;
4412         }
4413         serialVersionOnStream = currentSerialVersion;
4414         */
4415         ObjectInputStream.GetField fields = stream.readFields();
4416         this.symbols = (DecimalFormatSymbols) fields.get("symbols", null);
4417 
4418         initPattern("#");
4419 
4420         // Calling a setter method on an ICU DecimalFormat object will change the object's internal
4421         // state, even if the value set is the same as the default value (ICU Ticket #13266).
4422         //
4423         // In an attempt to create objects that are equals() to the ones that were serialized, it's
4424         // therefore assumed here that any values that are the same as the default values were the
4425         // default values (ie. no setter was called to explicitly set that value).
4426 
4427         String positivePrefix = (String) fields.get("positivePrefix", "");
4428         if (!Objects.equals(positivePrefix, icuDecimalFormat.getPositivePrefix())) {
4429             icuDecimalFormat.setPositivePrefix(positivePrefix);
4430         }
4431 
4432         String positiveSuffix = (String) fields.get("positiveSuffix", "");
4433         if (!Objects.equals(positiveSuffix, icuDecimalFormat.getPositiveSuffix())) {
4434             icuDecimalFormat.setPositiveSuffix(positiveSuffix);
4435         }
4436 
4437         String negativePrefix = (String) fields.get("negativePrefix", "-");
4438         if (!Objects.equals(negativePrefix, icuDecimalFormat.getNegativePrefix())) {
4439             icuDecimalFormat.setNegativePrefix(negativePrefix);
4440         }
4441 
4442         String negativeSuffix = (String) fields.get("negativeSuffix", "");
4443         if (!Objects.equals(negativeSuffix, icuDecimalFormat.getNegativeSuffix())) {
4444             icuDecimalFormat.setNegativeSuffix(negativeSuffix);
4445         }
4446 
4447         int multiplier = fields.get("multiplier", 1);
4448         if (multiplier != icuDecimalFormat.getMultiplier()) {
4449             icuDecimalFormat.setMultiplier(multiplier);
4450         }
4451 
4452         boolean groupingUsed = fields.get("groupingUsed", true);
4453         if (groupingUsed != icuDecimalFormat.isGroupingUsed()) {
4454             icuDecimalFormat.setGroupingUsed(groupingUsed);
4455         }
4456 
4457         int groupingSize = fields.get("groupingSize", (byte) 3);
4458         if (groupingSize != icuDecimalFormat.getGroupingSize()) {
4459             icuDecimalFormat.setGroupingSize(groupingSize);
4460         }
4461 
4462         boolean decimalSeparatorAlwaysShown = fields.get("decimalSeparatorAlwaysShown", false);
4463         if (decimalSeparatorAlwaysShown != icuDecimalFormat.isDecimalSeparatorAlwaysShown()) {
4464             icuDecimalFormat.setDecimalSeparatorAlwaysShown(decimalSeparatorAlwaysShown);
4465         }
4466 
4467         RoundingMode roundingMode =
4468                 (RoundingMode) fields.get("roundingMode", RoundingMode.HALF_EVEN);
4469         if (convertRoundingMode(roundingMode) != icuDecimalFormat.getRoundingMode()) {
4470             setRoundingMode(roundingMode);
4471         }
4472 
4473         int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309);
4474         if (maximumIntegerDigits != icuDecimalFormat.getMaximumIntegerDigits()) {
4475             icuDecimalFormat.setMaximumIntegerDigits(maximumIntegerDigits);
4476         }
4477 
4478         int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309);
4479         if (minimumIntegerDigits != icuDecimalFormat.getMinimumIntegerDigits()) {
4480             icuDecimalFormat.setMinimumIntegerDigits(minimumIntegerDigits);
4481         }
4482 
4483         int maximumFractionDigits = fields.get("maximumFractionDigits", 340);
4484         if (maximumFractionDigits != icuDecimalFormat.getMaximumFractionDigits()) {
4485             icuDecimalFormat.setMaximumFractionDigits(maximumFractionDigits);
4486         }
4487 
4488         int minimumFractionDigits = fields.get("minimumFractionDigits", 340);
4489         if (minimumFractionDigits != icuDecimalFormat.getMinimumFractionDigits()) {
4490             icuDecimalFormat.setMinimumFractionDigits(minimumFractionDigits);
4491         }
4492 
4493         boolean parseBigDecimal = fields.get("parseBigDecimal", true);
4494         if (parseBigDecimal != icuDecimalFormat.isParseBigDecimal()) {
4495             icuDecimalFormat.setParseBigDecimal(parseBigDecimal);
4496         }
4497 
4498         updateFieldsFromIcu();
4499 
4500         if (fields.get("serialVersionOnStream", 0) < 3) {
4501             setMaximumIntegerDigits(super.getMaximumIntegerDigits());
4502             setMinimumIntegerDigits(super.getMinimumIntegerDigits());
4503             setMaximumFractionDigits(super.getMaximumFractionDigits());
4504             setMinimumFractionDigits(super.getMinimumFractionDigits());
4505         }
4506         // END Android-changed: Custom serialization code for compatibility with RI serialization.
4507     }
4508 
4509     //----------------------------------------------------------------------
4510     // INSTANCE VARIABLES
4511     //----------------------------------------------------------------------
4512 
4513     // BEGIN Android-removed: various fields now stored in icuDecimalFormat.
4514     /*
4515     private transient DigitList digitList = new DigitList();
4516 
4517     /**
4518      * The symbol used as a prefix when formatting positive numbers, e.g. "+".
4519      *
4520      * @serial
4521      * @see #getPositivePrefix
4522      *
4523     private String  positivePrefix = "";
4524 
4525     /**
4526      * The symbol used as a suffix when formatting positive numbers.
4527      * This is often an empty string.
4528      *
4529      * @serial
4530      * @see #getPositiveSuffix
4531      *
4532     private String  positiveSuffix = "";
4533 
4534     /**
4535      * The symbol used as a prefix when formatting negative numbers, e.g. "-".
4536      *
4537      * @serial
4538      * @see #getNegativePrefix
4539      *
4540     private String  negativePrefix = "-";
4541 
4542     /**
4543      * The symbol used as a suffix when formatting negative numbers.
4544      * This is often an empty string.
4545      *
4546      * @serial
4547      * @see #getNegativeSuffix
4548      *
4549     private String  negativeSuffix = "";
4550 
4551     /**
4552      * The prefix pattern for non-negative numbers.  This variable corresponds
4553      * to <code>positivePrefix</code>.
4554      *
4555      * <p>This pattern is expanded by the method <code>expandAffix()</code> to
4556      * <code>positivePrefix</code> to update the latter to reflect changes in
4557      * <code>symbols</code>.  If this variable is <code>null</code> then
4558      * <code>positivePrefix</code> is taken as a literal value that does not
4559      * change when <code>symbols</code> changes.  This variable is always
4560      * <code>null</code> for <code>DecimalFormat</code> objects older than
4561      * stream version 2 restored from stream.
4562      *
4563      * @serial
4564      * @since 1.3
4565      *
4566     private String posPrefixPattern;
4567 
4568     /**
4569      * The suffix pattern for non-negative numbers.  This variable corresponds
4570      * to <code>positiveSuffix</code>.  This variable is analogous to
4571      * <code>posPrefixPattern</code>; see that variable for further
4572      * documentation.
4573      *
4574      * @serial
4575      * @since 1.3
4576      *
4577     private String posSuffixPattern;
4578 
4579     /**
4580      * The prefix pattern for negative numbers.  This variable corresponds
4581      * to <code>negativePrefix</code>.  This variable is analogous to
4582      * <code>posPrefixPattern</code>; see that variable for further
4583      * documentation.
4584      *
4585      * @serial
4586      * @since 1.3
4587      *
4588     private String negPrefixPattern;
4589 
4590     /**
4591      * The suffix pattern for negative numbers.  This variable corresponds
4592      * to <code>negativeSuffix</code>.  This variable is analogous to
4593      * <code>posPrefixPattern</code>; see that variable for further
4594      * documentation.
4595      *
4596      * @serial
4597      * @since 1.3
4598      *
4599     private String negSuffixPattern;
4600 
4601     /**
4602      * The multiplier for use in percent, per mille, etc.
4603      *
4604      * @serial
4605      * @see #getMultiplier
4606      *
4607     private int     multiplier = 1;
4608 
4609     /**
4610      * The number of digits between grouping separators in the integer
4611      * portion of a number.  Must be greater than 0 if
4612      * <code>NumberFormat.groupingUsed</code> is true.
4613      *
4614      * @serial
4615      * @see #getGroupingSize
4616      * @see java.text.NumberFormat#isGroupingUsed
4617      *
4618     private byte    groupingSize = 3;  // invariant, > 0 if useThousands
4619 
4620     /**
4621      * If true, forces the decimal separator to always appear in a formatted
4622      * number, even if the fractional part of the number is zero.
4623      *
4624      * @serial
4625      * @see #isDecimalSeparatorAlwaysShown
4626      *
4627     private boolean decimalSeparatorAlwaysShown = false;
4628 
4629     /**
4630      * If true, parse returns BigDecimal wherever possible.
4631      *
4632      * @serial
4633      * @see #isParseBigDecimal
4634      * @since 1.5
4635      *
4636     private boolean parseBigDecimal = false;
4637 
4638 
4639     /**
4640      * True if this object represents a currency format.  This determines
4641      * whether the monetary decimal separator is used instead of the normal one.
4642      *
4643     private transient boolean isCurrencyFormat = false;
4644     */
4645     // END Android-removed: various fields now stored in icuDecimalFormat.
4646 
4647     /**
4648      * The <code>DecimalFormatSymbols</code> object used by this format.
4649      * It contains the symbols used to format numbers, e.g. the grouping separator,
4650      * decimal separator, and so on.
4651      *
4652      * @serial
4653      * @see #setDecimalFormatSymbols
4654      * @see java.text.DecimalFormatSymbols
4655      */
4656     private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
4657 
4658     // BEGIN Android-removed: useExponentialNotation, *FieldPositions, minExponentDigits.
4659     /*
4660     /**
4661      * True to force the use of exponential (i.e. scientific) notation when formatting
4662      * numbers.
4663      *
4664      * @serial
4665      * @since 1.2
4666      *
4667     private boolean useExponentialNotation;  // Newly persistent in the Java 2 platform v.1.2
4668 
4669     /**
4670      * FieldPositions describing the positive prefix String. This is
4671      * lazily created. Use <code>getPositivePrefixFieldPositions</code>
4672      * when needed.
4673      *
4674     private transient FieldPosition[] positivePrefixFieldPositions;
4675 
4676     /**
4677      * FieldPositions describing the positive suffix String. This is
4678      * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
4679      * when needed.
4680      *
4681     private transient FieldPosition[] positiveSuffixFieldPositions;
4682 
4683     /**
4684      * FieldPositions describing the negative prefix String. This is
4685      * lazily created. Use <code>getNegativePrefixFieldPositions</code>
4686      * when needed.
4687      *
4688     private transient FieldPosition[] negativePrefixFieldPositions;
4689 
4690     /**
4691      * FieldPositions describing the negative suffix String. This is
4692      * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
4693      * when needed.
4694      *
4695     private transient FieldPosition[] negativeSuffixFieldPositions;
4696 
4697     /**
4698      * The minimum number of digits used to display the exponent when a number is
4699      * formatted in exponential notation.  This field is ignored if
4700      * <code>useExponentialNotation</code> is not true.
4701      *
4702      * @serial
4703      * @since 1.2
4704      *
4705     private byte    minExponentDigits;       // Newly persistent in the Java 2 platform v.1.2
4706 
4707 
4708     */
4709     // END Android-removed: useExponentialNotation, *FieldPositions, minExponentDigits.
4710 
4711     /**
4712      * The maximum number of digits allowed in the integer portion of a
4713      * <code>BigInteger</code> or <code>BigDecimal</code> number.
4714      * <code>maximumIntegerDigits</code> must be greater than or equal to
4715      * <code>minimumIntegerDigits</code>.
4716      *
4717      * @serial
4718      * @see #getMaximumIntegerDigits
4719      * @since 1.5
4720      */
4721     // Android-changed: removed initialization.
4722     private int    maximumIntegerDigits /* = super.getMaximumIntegerDigits() */;
4723 
4724     /**
4725      * The minimum number of digits allowed in the integer portion of a
4726      * <code>BigInteger</code> or <code>BigDecimal</code> number.
4727      * <code>minimumIntegerDigits</code> must be less than or equal to
4728      * <code>maximumIntegerDigits</code>.
4729      *
4730      * @serial
4731      * @see #getMinimumIntegerDigits
4732      * @since 1.5
4733      */
4734     // Android-changed: removed initialization.
4735     private int    minimumIntegerDigits /* = super.getMinimumIntegerDigits() */;
4736 
4737     /**
4738      * The maximum number of digits allowed in the fractional portion of a
4739      * <code>BigInteger</code> or <code>BigDecimal</code> number.
4740      * <code>maximumFractionDigits</code> must be greater than or equal to
4741      * <code>minimumFractionDigits</code>.
4742      *
4743      * @serial
4744      * @see #getMaximumFractionDigits
4745      * @since 1.5
4746      */
4747     // Android-changed: removed initialization.
4748     private int    maximumFractionDigits /* = super.getMaximumFractionDigits() */;
4749 
4750     /**
4751      * The minimum number of digits allowed in the fractional portion of a
4752      * <code>BigInteger</code> or <code>BigDecimal</code> number.
4753      * <code>minimumFractionDigits</code> must be less than or equal to
4754      * <code>maximumFractionDigits</code>.
4755      *
4756      * @serial
4757      * @see #getMinimumFractionDigits
4758      * @since 1.5
4759      */
4760     // Android-changed: removed initialization.
4761     private int    minimumFractionDigits /* = super.getMinimumFractionDigits() */;
4762 
4763     /**
4764      * The {@link java.math.RoundingMode} used in this DecimalFormat.
4765      *
4766      * @serial
4767      * @since 1.6
4768      */
4769     private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
4770 
4771     // BEGIN Android-removed: FastPathData, isFastPath, fastPathCheckNeeded and fastPathData.
4772     /*
4773     // ------ DecimalFormat fields for fast-path for double algorithm  ------
4774 
4775     /**
4776      * Helper inner utility class for storing the data used in the fast-path
4777      * algorithm. Almost all fields related to fast-path are encapsulated in
4778      * this class.
4779      *
4780      * Any {@code DecimalFormat} instance has a {@code fastPathData}
4781      * reference field that is null unless both the properties of the instance
4782      * are such that the instance is in the "fast-path" state, and a format call
4783      * has been done at least once while in this state.
4784      *
4785      * Almost all fields are related to the "fast-path" state only and don't
4786      * change until one of the instance properties is changed.
4787      *
4788      * {@code firstUsedIndex} and {@code lastFreeIndex} are the only
4789      * two fields that are used and modified while inside a call to
4790      * {@code fastDoubleFormat}.
4791      *
4792      *
4793     private static class FastPathData {
4794         // --- Temporary fields used in fast-path, shared by several methods.
4795 
4796         /** The first unused index at the end of the formatted result. *
4797         int lastFreeIndex;
4798 
4799         /** The first used index at the beginning of the formatted result *
4800         int firstUsedIndex;
4801 
4802         // --- State fields related to fast-path status. Changes due to a
4803         //     property change only. Set by checkAndSetFastPathStatus() only.
4804 
4805         /** Difference between locale zero and default zero representation. *
4806         int  zeroDelta;
4807 
4808         /** Locale char for grouping separator. *
4809         char groupingChar;
4810 
4811         /**  Fixed index position of last integral digit of formatted result *
4812         int integralLastIndex;
4813 
4814         /**  Fixed index position of first fractional digit of formatted result *
4815         int fractionalFirstIndex;
4816 
4817         /** Fractional constants depending on decimal|currency state *
4818         double fractionalScaleFactor;
4819         int fractionalMaxIntBound;
4820 
4821 
4822         /** The char array buffer that will contain the formatted result *
4823         char[] fastPathContainer;
4824 
4825         /** Suffixes recorded as char array for efficiency. *
4826         char[] charsPositivePrefix;
4827         char[] charsNegativePrefix;
4828         char[] charsPositiveSuffix;
4829         char[] charsNegativeSuffix;
4830         boolean positiveAffixesRequired = true;
4831         boolean negativeAffixesRequired = true;
4832     }
4833 
4834     /** The format fast-path status of the instance. Logical state. *
4835     private transient boolean isFastPath = false;
4836 
4837     /** Flag stating need of check and reinit fast-path status on next format call. *
4838     private transient boolean fastPathCheckNeeded = true;
4839 
4840     /** DecimalFormat reference to its FastPathData *
4841     private transient FastPathData fastPathData;
4842     */
4843     // END Android-removed: FastPathData, isFastPath, fastPathCheckNeeded and fastPathData.
4844 
4845     //----------------------------------------------------------------------
4846 
4847     static final int currentSerialVersion = 4;
4848 
4849     // BEGIN Android-removed: serialVersionOnStream.
4850 
4851     /**
4852      * The internal serial version which says which version was written.
4853      * Possible values are:
4854      * <ul>
4855      * <li><b>0</b> (default): versions before the Java 2 platform v1.2
4856      * <li><b>1</b>: version for 1.2, which includes the two new fields
4857      *      <code>useExponentialNotation</code> and
4858      *      <code>minExponentDigits</code>.
4859      * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
4860      *      <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
4861      *      <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
4862      * <li><b>3</b>: version for 1.5 and later, which adds five new fields:
4863      *      <code>maximumIntegerDigits</code>,
4864      *      <code>minimumIntegerDigits</code>,
4865      *      <code>maximumFractionDigits</code>,
4866      *      <code>minimumFractionDigits</code>, and
4867      *      <code>parseBigDecimal</code>.
4868      * <li><b>4</b>: version for 1.6 and later, which adds one new field:
4869      *      <code>roundingMode</code>.
4870      * </ul>
4871      * @since 1.2
4872      * @serial
4873      *
4874     private int serialVersionOnStream = currentSerialVersion;
4875     */
4876     // END Android-removed: serialVersionOnStream.
4877 
4878     //----------------------------------------------------------------------
4879     // CONSTANTS
4880     //----------------------------------------------------------------------
4881 
4882     // BEGIN Android-removed: Fast-Path for double Constants, various constants.
4883     /*
4884     // ------ Fast-Path for double Constants ------
4885 
4886     /** Maximum valid integer value for applying fast-path algorithm *
4887     private static final double MAX_INT_AS_DOUBLE = (double) Integer.MAX_VALUE;
4888 
4889     /**
4890      * The digit arrays used in the fast-path methods for collecting digits.
4891      * Using 3 constants arrays of chars ensures a very fast collection of digits
4892      *
4893     private static class DigitArrays {
4894         static final char[] DigitOnes1000 = new char[1000];
4895         static final char[] DigitTens1000 = new char[1000];
4896         static final char[] DigitHundreds1000 = new char[1000];
4897 
4898         // initialize on demand holder class idiom for arrays of digits
4899         static {
4900             int tenIndex = 0;
4901             int hundredIndex = 0;
4902             char digitOne = '0';
4903             char digitTen = '0';
4904             char digitHundred = '0';
4905             for (int i = 0;  i < 1000; i++ ) {
4906 
4907                 DigitOnes1000[i] = digitOne;
4908                 if (digitOne == '9')
4909                     digitOne = '0';
4910                 else
4911                     digitOne++;
4912 
4913                 DigitTens1000[i] = digitTen;
4914                 if (i == (tenIndex + 9)) {
4915                     tenIndex += 10;
4916                     if (digitTen == '9')
4917                         digitTen = '0';
4918                     else
4919                         digitTen++;
4920                 }
4921 
4922                 DigitHundreds1000[i] = digitHundred;
4923                 if (i == (hundredIndex + 99)) {
4924                     digitHundred++;
4925                     hundredIndex += 100;
4926                 }
4927             }
4928         }
4929     }
4930     // ------ Fast-Path for double Constants end ------
4931 
4932     // Constants for characters used in programmatic (unlocalized) patterns.
4933     private static final char       PATTERN_ZERO_DIGIT         = '0';
4934     private static final char       PATTERN_GROUPING_SEPARATOR = ',';
4935     private static final char       PATTERN_DECIMAL_SEPARATOR  = '.';
4936     private static final char       PATTERN_PER_MILLE          = '\u2030';
4937     private static final char       PATTERN_PERCENT            = '%';
4938     private static final char       PATTERN_DIGIT              = '#';
4939     private static final char       PATTERN_SEPARATOR          = ';';
4940     private static final String     PATTERN_EXPONENT           = "E";
4941     private static final char       PATTERN_MINUS              = '-';
4942 
4943     /**
4944      * The CURRENCY_SIGN is the standard Unicode symbol for currency.  It
4945      * is used in patterns and substituted with either the currency symbol,
4946      * or if it is doubled, with the international currency symbol.  If the
4947      * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
4948      * replaced with the monetary decimal separator.
4949      *
4950      * The CURRENCY_SIGN is not localized.
4951      *
4952     private static final char       CURRENCY_SIGN = '\u00A4';
4953 
4954     private static final char       QUOTE = '\'';
4955 
4956     private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0];
4957     */
4958     // END Android-removed: Fast-Path for double Constants, various constants.
4959 
4960     // Upper limit on integer and fraction digits for a Java double
4961     static final int DOUBLE_INTEGER_DIGITS  = 309;
4962     static final int DOUBLE_FRACTION_DIGITS = 340;
4963 
4964     // Upper limit on integer and fraction digits for BigDecimal and BigInteger
4965     static final int MAXIMUM_INTEGER_DIGITS  = Integer.MAX_VALUE;
4966     static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE;
4967 
4968     // Proclaim JDK 1.1 serial compatibility.
4969     static final long serialVersionUID = 864413376551465018L;
4970 }
4971