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