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