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