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