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