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