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.length() != 0) 1076 || (positiveSuffix.length() != 0); 1077 fastPathData.negativeAffixesRequired 1078 = (negativePrefix.length() != 0) 1079 || (negativeSuffix.length() != 0); 1080 1081 // Creates a cached char container for result, with max possible size. 1082 int maxNbIntegralDigits = 10; 1083 int maxNbGroups = 3; 1084 int containerSize 1085 = Math.max(positivePrefix.length(), negativePrefix.length()) 1086 + maxNbIntegralDigits + maxNbGroups + 1 1087 + maximumFractionDigits 1088 + Math.max(positiveSuffix.length(), negativeSuffix.length()); 1089 1090 fastPathData.fastPathContainer = new char[containerSize]; 1091 1092 // Sets up prefix and suffix char arrays constants. 1093 fastPathData.charsPositiveSuffix = positiveSuffix.toCharArray(); 1094 fastPathData.charsNegativeSuffix = negativeSuffix.toCharArray(); 1095 fastPathData.charsPositivePrefix = positivePrefix.toCharArray(); 1096 fastPathData.charsNegativePrefix = negativePrefix.toCharArray(); 1097 1098 // Sets up fixed index positions for integral and fractional digits. 1099 // Sets up decimal point in cached result container. 1100 int longestPrefixLength 1101 = Math.max(positivePrefix.length(), 1102 negativePrefix.length()); 1103 int decimalPointIndex 1104 = maxNbIntegralDigits + maxNbGroups + longestPrefixLength; 1105 1106 fastPathData.integralLastIndex = decimalPointIndex - 1; 1107 fastPathData.fractionalFirstIndex = decimalPointIndex + 1; 1108 fastPathData.fastPathContainer[decimalPointIndex] 1109 = isCurrencyFormat 1110 ? symbols.getMonetaryDecimalSeparator() 1111 : symbols.getDecimalSeparator(); 1112 1113 } else if (fastPathWasOn) { 1114 // Previous state was fast-path and is no more. 1115 // Resets cached array constants. 1116 fastPathData.fastPathContainer = null; 1117 fastPathData.charsPositiveSuffix = null; 1118 fastPathData.charsNegativeSuffix = null; 1119 fastPathData.charsPositivePrefix = null; 1120 fastPathData.charsNegativePrefix = null; 1121 } 1122 } 1123 1124 /** 1125 * Returns true if rounding-up must be done on {@code scaledFractionalPartAsInt}, 1126 * false otherwise. 1127 * 1128 * This is a utility method that takes correct half-even rounding decision on 1129 * passed fractional value at the scaled decimal point (2 digits for currency 1130 * case and 3 for decimal case), when the approximated fractional part after 1131 * scaled decimal point is exactly 0.5d. This is done by means of exact 1132 * calculations on the {@code fractionalPart} floating-point value. 1133 * 1134 * This method is supposed to be called by private {@code fastDoubleFormat} 1135 * method only. 1136 * 1137 * The algorithms used for the exact calculations are : 1138 * 1139 * The <b><i>FastTwoSum</i></b> algorithm, from T.J.Dekker, described in the 1140 * papers "<i>A Floating-Point Technique for Extending the Available 1141 * Precision</i>" by Dekker, and in "<i>Adaptive Precision Floating-Point 1142 * Arithmetic and Fast Robust Geometric Predicates</i>" from J.Shewchuk. 1143 * 1144 * A modified version of <b><i>Sum2S</i></b> cascaded summation described in 1145 * "<i>Accurate Sum and Dot Product</i>" from Takeshi Ogita and All. As 1146 * Ogita says in this paper this is an equivalent of the Kahan-Babuska's 1147 * summation algorithm because we order the terms by magnitude before summing 1148 * them. For this reason we can use the <i>FastTwoSum</i> algorithm rather 1149 * than the more expensive Knuth's <i>TwoSum</i>. 1150 * 1151 * We do this to avoid a more expensive exact "<i>TwoProduct</i>" algorithm, 1152 * like those described in Shewchuk's paper above. See comments in the code 1153 * below. 1154 * 1155 * @param fractionalPart The fractional value on which we take rounding 1156 * decision. 1157 * @param scaledFractionalPartAsInt The integral part of the scaled 1158 * fractional value. 1159 * 1160 * @return the decision that must be taken regarding half-even rounding. 1161 */ 1162 private boolean exactRoundUp(double fractionalPart, 1163 int scaledFractionalPartAsInt) { 1164 1165 /* exactRoundUp() method is called by fastDoubleFormat() only. 1166 * The precondition expected to be verified by the passed parameters is : 1167 * scaledFractionalPartAsInt == 1168 * (int) (fractionalPart * fastPathData.fractionalScaleFactor). 1169 * This is ensured by fastDoubleFormat() code. 1170 */ 1171 1172 /* We first calculate roundoff error made by fastDoubleFormat() on 1173 * the scaled fractional part. We do this with exact calculation on the 1174 * passed fractionalPart. Rounding decision will then be taken from roundoff. 1175 */ 1176 1177 /* ---- TwoProduct(fractionalPart, scale factor (i.e. 1000.0d or 100.0d)). 1178 * 1179 * The below is an optimized exact "TwoProduct" calculation of passed 1180 * fractional part with scale factor, using Ogita's Sum2S cascaded 1181 * summation adapted as Kahan-Babuska equivalent by using FastTwoSum 1182 * (much faster) rather than Knuth's TwoSum. 1183 * 1184 * We can do this because we order the summation from smallest to 1185 * greatest, so that FastTwoSum can be used without any additional error. 1186 * 1187 * The "TwoProduct" exact calculation needs 17 flops. We replace this by 1188 * a cascaded summation of FastTwoSum calculations, each involving an 1189 * exact multiply by a power of 2. 1190 * 1191 * Doing so saves overall 4 multiplications and 1 addition compared to 1192 * using traditional "TwoProduct". 1193 * 1194 * The scale factor is either 100 (currency case) or 1000 (decimal case). 1195 * - when 1000, we replace it by (1024 - 16 - 8) = 1000. 1196 * - when 100, we replace it by (128 - 32 + 4) = 100. 1197 * Every multiplication by a power of 2 (1024, 128, 32, 16, 8, 4) is exact. 1198 * 1199 */ 1200 double approxMax; // Will always be positive. 1201 double approxMedium; // Will always be negative. 1202 double approxMin; 1203 1204 double fastTwoSumApproximation = 0.0d; 1205 double fastTwoSumRoundOff = 0.0d; 1206 double bVirtual = 0.0d; 1207 1208 if (isCurrencyFormat) { 1209 // Scale is 100 = 128 - 32 + 4. 1210 // Multiply by 2**n is a shift. No roundoff. No error. 1211 approxMax = fractionalPart * 128.00d; 1212 approxMedium = - (fractionalPart * 32.00d); 1213 approxMin = fractionalPart * 4.00d; 1214 } else { 1215 // Scale is 1000 = 1024 - 16 - 8. 1216 // Multiply by 2**n is a shift. No roundoff. No error. 1217 approxMax = fractionalPart * 1024.00d; 1218 approxMedium = - (fractionalPart * 16.00d); 1219 approxMin = - (fractionalPart * 8.00d); 1220 } 1221 1222 // Shewchuk/Dekker's FastTwoSum(approxMedium, approxMin). 1223 assert(-approxMedium >= Math.abs(approxMin)); 1224 fastTwoSumApproximation = approxMedium + approxMin; 1225 bVirtual = fastTwoSumApproximation - approxMedium; 1226 fastTwoSumRoundOff = approxMin - bVirtual; 1227 double approxS1 = fastTwoSumApproximation; 1228 double roundoffS1 = fastTwoSumRoundOff; 1229 1230 // Shewchuk/Dekker's FastTwoSum(approxMax, approxS1); 1231 assert(approxMax >= Math.abs(approxS1)); 1232 fastTwoSumApproximation = approxMax + approxS1; 1233 bVirtual = fastTwoSumApproximation - approxMax; 1234 fastTwoSumRoundOff = approxS1 - bVirtual; 1235 double roundoff1000 = fastTwoSumRoundOff; 1236 double approx1000 = fastTwoSumApproximation; 1237 double roundoffTotal = roundoffS1 + roundoff1000; 1238 1239 // Shewchuk/Dekker's FastTwoSum(approx1000, roundoffTotal); 1240 assert(approx1000 >= Math.abs(roundoffTotal)); 1241 fastTwoSumApproximation = approx1000 + roundoffTotal; 1242 bVirtual = fastTwoSumApproximation - approx1000; 1243 1244 // Now we have got the roundoff for the scaled fractional 1245 double scaledFractionalRoundoff = roundoffTotal - bVirtual; 1246 1247 // ---- TwoProduct(fractionalPart, scale (i.e. 1000.0d or 100.0d)) end. 1248 1249 /* ---- Taking the rounding decision 1250 * 1251 * We take rounding decision based on roundoff and half-even rounding 1252 * rule. 1253 * 1254 * The above TwoProduct gives us the exact roundoff on the approximated 1255 * scaled fractional, and we know that this approximation is exactly 1256 * 0.5d, since that has already been tested by the caller 1257 * (fastDoubleFormat). 1258 * 1259 * Decision comes first from the sign of the calculated exact roundoff. 1260 * - Since being exact roundoff, it cannot be positive with a scaled 1261 * fractional less than 0.5d, as well as negative with a scaled 1262 * fractional greater than 0.5d. That leaves us with following 3 cases. 1263 * - positive, thus scaled fractional == 0.500....0fff ==> round-up. 1264 * - negative, thus scaled fractional == 0.499....9fff ==> don't round-up. 1265 * - is zero, thus scaled fractioanl == 0.5 ==> half-even rounding applies : 1266 * we round-up only if the integral part of the scaled fractional is odd. 1267 * 1268 */ 1269 if (scaledFractionalRoundoff > 0.0) { 1270 return true; 1271 } else if (scaledFractionalRoundoff < 0.0) { 1272 return false; 1273 } else if ((scaledFractionalPartAsInt & 1) != 0) { 1274 return true; 1275 } 1276 1277 return false; 1278 1279 // ---- Taking the rounding decision end 1280 } 1281 1282 /** 1283 * Collects integral digits from passed {@code number}, while setting 1284 * grouping chars as needed. Updates {@code firstUsedIndex} accordingly. 1285 * 1286 * Loops downward starting from {@code backwardIndex} position (inclusive). 1287 * 1288 * @param number The int value from which we collect digits. 1289 * @param digitsBuffer The char array container where digits and grouping chars 1290 * are stored. 1291 * @param backwardIndex the position from which we start storing digits in 1292 * digitsBuffer. 1293 * 1294 */ 1295 private void collectIntegralDigits(int number, 1296 char[] digitsBuffer, 1297 int backwardIndex) { 1298 int index = backwardIndex; 1299 int q; 1300 int r; 1301 while (number > 999) { 1302 // Generates 3 digits per iteration. 1303 q = number / 1000; 1304 r = number - (q << 10) + (q << 4) + (q << 3); // -1024 +16 +8 = 1000. 1305 number = q; 1306 1307 digitsBuffer[index--] = DigitArrays.DigitOnes1000[r]; 1308 digitsBuffer[index--] = DigitArrays.DigitTens1000[r]; 1309 digitsBuffer[index--] = DigitArrays.DigitHundreds1000[r]; 1310 digitsBuffer[index--] = fastPathData.groupingChar; 1311 } 1312 1313 // Collects last 3 or less digits. 1314 digitsBuffer[index] = DigitArrays.DigitOnes1000[number]; 1315 if (number > 9) { 1316 digitsBuffer[--index] = DigitArrays.DigitTens1000[number]; 1317 if (number > 99) 1318 digitsBuffer[--index] = DigitArrays.DigitHundreds1000[number]; 1319 } 1320 1321 fastPathData.firstUsedIndex = index; 1322 } 1323 1324 /** 1325 * Collects the 2 (currency) or 3 (decimal) fractional digits from passed 1326 * {@code number}, starting at {@code startIndex} position 1327 * inclusive. There is no punctuation to set here (no grouping chars). 1328 * Updates {@code fastPathData.lastFreeIndex} accordingly. 1329 * 1330 * 1331 * @param number The int value from which we collect digits. 1332 * @param digitsBuffer The char array container where digits are stored. 1333 * @param startIndex the position from which we start storing digits in 1334 * digitsBuffer. 1335 * 1336 */ 1337 private void collectFractionalDigits(int number, 1338 char[] digitsBuffer, 1339 int startIndex) { 1340 int index = startIndex; 1341 1342 char digitOnes = DigitArrays.DigitOnes1000[number]; 1343 char digitTens = DigitArrays.DigitTens1000[number]; 1344 1345 if (isCurrencyFormat) { 1346 // Currency case. Always collects fractional digits. 1347 digitsBuffer[index++] = digitTens; 1348 digitsBuffer[index++] = digitOnes; 1349 } else if (number != 0) { 1350 // Decimal case. Hundreds will always be collected 1351 digitsBuffer[index++] = DigitArrays.DigitHundreds1000[number]; 1352 1353 // Ending zeros won't be collected. 1354 if (digitOnes != '0') { 1355 digitsBuffer[index++] = digitTens; 1356 digitsBuffer[index++] = digitOnes; 1357 } else if (digitTens != '0') 1358 digitsBuffer[index++] = digitTens; 1359 1360 } else 1361 // This is decimal pattern and fractional part is zero. 1362 // We must remove decimal point from result. 1363 index--; 1364 1365 fastPathData.lastFreeIndex = index; 1366 } 1367 1368 /** 1369 * Internal utility. 1370 * Adds the passed {@code prefix} and {@code suffix} to {@code container}. 1371 * 1372 * @param container Char array container which to prepend/append the 1373 * prefix/suffix. 1374 * @param prefix Char sequence to prepend as a prefix. 1375 * @param suffix Char sequence to append as a suffix. 1376 * 1377 */ 1378 // private void addAffixes(boolean isNegative, char[] container) { 1379 private void addAffixes(char[] container, char[] prefix, char[] suffix) { 1380 1381 // We add affixes only if needed (affix length > 0). 1382 int pl = prefix.length; 1383 int sl = suffix.length; 1384 if (pl != 0) prependPrefix(prefix, pl, container); 1385 if (sl != 0) appendSuffix(suffix, sl, container); 1386 1387 } 1388 1389 /** 1390 * Prepends the passed {@code prefix} chars to given result 1391 * {@code container}. Updates {@code fastPathData.firstUsedIndex} 1392 * accordingly. 1393 * 1394 * @param prefix The prefix characters to prepend to result. 1395 * @param len The number of chars to prepend. 1396 * @param container Char array container which to prepend the prefix 1397 */ 1398 private void prependPrefix(char[] prefix, 1399 int len, 1400 char[] container) { 1401 1402 fastPathData.firstUsedIndex -= len; 1403 int startIndex = fastPathData.firstUsedIndex; 1404 1405 // If prefix to prepend is only 1 char long, just assigns this char. 1406 // If prefix is less or equal 4, we use a dedicated algorithm that 1407 // has shown to run faster than System.arraycopy. 1408 // If more than 4, we use System.arraycopy. 1409 if (len == 1) 1410 container[startIndex] = prefix[0]; 1411 else if (len <= 4) { 1412 int dstLower = startIndex; 1413 int dstUpper = dstLower + len - 1; 1414 int srcUpper = len - 1; 1415 container[dstLower] = prefix[0]; 1416 container[dstUpper] = prefix[srcUpper]; 1417 1418 if (len > 2) 1419 container[++dstLower] = prefix[1]; 1420 if (len == 4) 1421 container[--dstUpper] = prefix[2]; 1422 } else 1423 System.arraycopy(prefix, 0, container, startIndex, len); 1424 } 1425 1426 /** 1427 * Appends the passed {@code suffix} chars to given result 1428 * {@code container}. Updates {@code fastPathData.lastFreeIndex} 1429 * accordingly. 1430 * 1431 * @param suffix The suffix characters to append to result. 1432 * @param len The number of chars to append. 1433 * @param container Char array container which to append the suffix 1434 */ 1435 private void appendSuffix(char[] suffix, 1436 int len, 1437 char[] container) { 1438 1439 int startIndex = fastPathData.lastFreeIndex; 1440 1441 // If suffix to append is only 1 char long, just assigns this char. 1442 // If suffix is less or equal 4, we use a dedicated algorithm that 1443 // has shown to run faster than System.arraycopy. 1444 // If more than 4, we use System.arraycopy. 1445 if (len == 1) 1446 container[startIndex] = suffix[0]; 1447 else if (len <= 4) { 1448 int dstLower = startIndex; 1449 int dstUpper = dstLower + len - 1; 1450 int srcUpper = len - 1; 1451 container[dstLower] = suffix[0]; 1452 container[dstUpper] = suffix[srcUpper]; 1453 1454 if (len > 2) 1455 container[++dstLower] = suffix[1]; 1456 if (len == 4) 1457 container[--dstUpper] = suffix[2]; 1458 } else 1459 System.arraycopy(suffix, 0, container, startIndex, len); 1460 1461 fastPathData.lastFreeIndex += len; 1462 } 1463 1464 /** 1465 * Converts digit chars from {@code digitsBuffer} to current locale. 1466 * 1467 * Must be called before adding affixes since we refer to 1468 * {@code fastPathData.firstUsedIndex} and {@code fastPathData.lastFreeIndex}, 1469 * and do not support affixes (for speed reason). 1470 * 1471 * We loop backward starting from last used index in {@code fastPathData}. 1472 * 1473 * @param digitsBuffer The char array container where the digits are stored. 1474 */ 1475 private void localizeDigits(char[] digitsBuffer) { 1476 1477 // We will localize only the digits, using the groupingSize, 1478 // and taking into account fractional part. 1479 1480 // First take into account fractional part. 1481 int digitsCounter = 1482 fastPathData.lastFreeIndex - fastPathData.fractionalFirstIndex; 1483 1484 // The case when there is no fractional digits. 1485 if (digitsCounter < 0) 1486 digitsCounter = groupingSize; 1487 1488 // Only the digits remains to localize. 1489 for (int cursor = fastPathData.lastFreeIndex - 1; 1490 cursor >= fastPathData.firstUsedIndex; 1491 cursor--) { 1492 if (digitsCounter != 0) { 1493 // This is a digit char, we must localize it. 1494 digitsBuffer[cursor] += fastPathData.zeroDelta; 1495 digitsCounter--; 1496 } else { 1497 // Decimal separator or grouping char. Reinit counter only. 1498 digitsCounter = groupingSize; 1499 } 1500 } 1501 } 1502 1503 /** 1504 * This is the main entry point for the fast-path format algorithm. 1505 * 1506 * At this point we are sure to be in the expected conditions to run it. 1507 * This algorithm builds the formatted result and puts it in the dedicated 1508 * {@code fastPathData.fastPathContainer}. 1509 * 1510 * @param d the double value to be formatted. 1511 * @param negative Flag precising if {@code d} is negative. 1512 */ 1513 private void fastDoubleFormat(double d, 1514 boolean negative) { 1515 1516 char[] container = fastPathData.fastPathContainer; 1517 1518 /* 1519 * The principle of the algorithm is to : 1520 * - Break the passed double into its integral and fractional parts 1521 * converted into integers. 1522 * - Then decide if rounding up must be applied or not by following 1523 * the half-even rounding rule, first using approximated scaled 1524 * fractional part. 1525 * - For the difficult cases (approximated scaled fractional part 1526 * being exactly 0.5d), we refine the rounding decision by calling 1527 * exactRoundUp utility method that both calculates the exact roundoff 1528 * on the approximation and takes correct rounding decision. 1529 * - We round-up the fractional part if needed, possibly propagating the 1530 * rounding to integral part if we meet a "all-nine" case for the 1531 * scaled fractional part. 1532 * - We then collect digits from the resulting integral and fractional 1533 * parts, also setting the required grouping chars on the fly. 1534 * - Then we localize the collected digits if needed, and 1535 * - Finally prepend/append prefix/suffix if any is needed. 1536 */ 1537 1538 // Exact integral part of d. 1539 int integralPartAsInt = (int) d; 1540 1541 // Exact fractional part of d (since we subtract it's integral part). 1542 double exactFractionalPart = d - (double) integralPartAsInt; 1543 1544 // Approximated scaled fractional part of d (due to multiplication). 1545 double scaledFractional = 1546 exactFractionalPart * fastPathData.fractionalScaleFactor; 1547 1548 // Exact integral part of scaled fractional above. 1549 int fractionalPartAsInt = (int) scaledFractional; 1550 1551 // Exact fractional part of scaled fractional above. 1552 scaledFractional = scaledFractional - (double) fractionalPartAsInt; 1553 1554 // Only when scaledFractional is exactly 0.5d do we have to do exact 1555 // calculations and take fine-grained rounding decision, since 1556 // approximated results above may lead to incorrect decision. 1557 // Otherwise comparing against 0.5d (strictly greater or less) is ok. 1558 boolean roundItUp = false; 1559 if (scaledFractional >= 0.5d) { 1560 if (scaledFractional == 0.5d) 1561 // Rounding need fine-grained decision. 1562 roundItUp = exactRoundUp(exactFractionalPart, fractionalPartAsInt); 1563 else 1564 roundItUp = true; 1565 1566 if (roundItUp) { 1567 // Rounds up both fractional part (and also integral if needed). 1568 if (fractionalPartAsInt < fastPathData.fractionalMaxIntBound) { 1569 fractionalPartAsInt++; 1570 } else { 1571 // Propagates rounding to integral part since "all nines" case. 1572 fractionalPartAsInt = 0; 1573 integralPartAsInt++; 1574 } 1575 } 1576 } 1577 1578 // Collecting digits. 1579 collectFractionalDigits(fractionalPartAsInt, container, 1580 fastPathData.fractionalFirstIndex); 1581 collectIntegralDigits(integralPartAsInt, container, 1582 fastPathData.integralLastIndex); 1583 1584 // Localizing digits. 1585 if (fastPathData.zeroDelta != 0) 1586 localizeDigits(container); 1587 1588 // Adding prefix and suffix. 1589 if (negative) { 1590 if (fastPathData.negativeAffixesRequired) 1591 addAffixes(container, 1592 fastPathData.charsNegativePrefix, 1593 fastPathData.charsNegativeSuffix); 1594 } else if (fastPathData.positiveAffixesRequired) 1595 addAffixes(container, 1596 fastPathData.charsPositivePrefix, 1597 fastPathData.charsPositiveSuffix); 1598 } 1599 1600 /** 1601 * A fast-path shortcut of format(double) to be called by NumberFormat, or by 1602 * format(double, ...) public methods. 1603 * 1604 * If instance can be applied fast-path and passed double is not NaN or 1605 * Infinity, is in the integer range, we call {@code fastDoubleFormat} 1606 * after changing {@code d} to its positive value if necessary. 1607 * 1608 * Otherwise returns null by convention since fast-path can't be exercized. 1609 * 1610 * @param d The double value to be formatted 1611 * 1612 * @return the formatted result for {@code d} as a string. 1613 */ 1614 String fastFormat(double d) { 1615 boolean isDataSet = false; 1616 // (Re-)Evaluates fast-path status if needed. 1617 if (fastPathCheckNeeded) { 1618 isDataSet = checkAndSetFastPathStatus(); 1619 } 1620 1621 if (!isFastPath ) 1622 // DecimalFormat instance is not in a fast-path state. 1623 return null; 1624 1625 if (!Double.isFinite(d)) 1626 // Should not use fast-path for Infinity and NaN. 1627 return null; 1628 1629 // Extracts and records sign of double value, possibly changing it 1630 // to a positive one, before calling fastDoubleFormat(). 1631 boolean negative = false; 1632 if (d < 0.0d) { 1633 negative = true; 1634 d = -d; 1635 } else if (d == 0.0d) { 1636 negative = (Math.copySign(1.0d, d) == -1.0d); 1637 d = +0.0d; 1638 } 1639 1640 if (d > MAX_INT_AS_DOUBLE) 1641 // Filters out values that are outside expected fast-path range 1642 return null; 1643 else { 1644 if (!isDataSet) { 1645 /* 1646 * If the fast path data is not set through 1647 * checkAndSetFastPathStatus() and fulfil the 1648 * fast path conditions then reset the data 1649 * directly through resetFastPathData() 1650 */ 1651 resetFastPathData(isFastPath); 1652 } 1653 fastDoubleFormat(d, negative); 1654 1655 } 1656 1657 1658 // Returns a new string from updated fastPathContainer. 1659 return new String(fastPathData.fastPathContainer, 1660 fastPathData.firstUsedIndex, 1661 fastPathData.lastFreeIndex - fastPathData.firstUsedIndex); 1662 1663 } 1664 1665 // ======== End fast-path formating logic for double ========================= 1666 1667 /** 1668 * Complete the formatting of a finite number. On entry, the digitList must 1669 * be filled in with the correct digits. 1670 */ 1671 private StringBuffer subformat(StringBuffer result, FieldDelegate delegate, 1672 boolean isNegative, boolean isInteger, 1673 int maxIntDigits, int minIntDigits, 1674 int maxFraDigits, int minFraDigits) { 1675 // NOTE: This isn't required anymore because DigitList takes care of this. 1676 // 1677 // // The negative of the exponent represents the number of leading 1678 // // zeros between the decimal and the first non-zero digit, for 1679 // // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this 1680 // // is more than the maximum fraction digits, then we have an underflow 1681 // // for the printed representation. We recognize this here and set 1682 // // the DigitList representation to zero in this situation. 1683 // 1684 // if (-digitList.decimalAt >= getMaximumFractionDigits()) 1685 // { 1686 // digitList.count = 0; 1687 // } 1688 1689 char zero = symbols.getZeroDigit(); 1690 int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero 1691 char grouping = symbols.getGroupingSeparator(); 1692 char decimal = isCurrencyFormat ? 1693 symbols.getMonetaryDecimalSeparator() : 1694 symbols.getDecimalSeparator(); 1695 1696 /* Per bug 4147706, DecimalFormat must respect the sign of numbers which 1697 * format as zero. This allows sensible computations and preserves 1698 * relations such as signum(1/x) = signum(x), where x is +Infinity or 1699 * -Infinity. Prior to this fix, we always formatted zero values as if 1700 * they were positive. Liu 7/6/98. 1701 */ 1702 if (digitList.isZero()) { 1703 digitList.decimalAt = 0; // Normalize 1704 } 1705 1706 if (isNegative) { 1707 append(result, negativePrefix, delegate, 1708 getNegativePrefixFieldPositions(), Field.SIGN); 1709 } else { 1710 append(result, positivePrefix, delegate, 1711 getPositivePrefixFieldPositions(), Field.SIGN); 1712 } 1713 1714 if (useExponentialNotation) { 1715 int iFieldStart = result.length(); 1716 int iFieldEnd = -1; 1717 int fFieldStart = -1; 1718 1719 // Minimum integer digits are handled in exponential format by 1720 // adjusting the exponent. For example, 0.01234 with 3 minimum 1721 // integer digits is "123.4E-4". 1722 1723 // Maximum integer digits are interpreted as indicating the 1724 // repeating range. This is useful for engineering notation, in 1725 // which the exponent is restricted to a multiple of 3. For 1726 // example, 0.01234 with 3 maximum integer digits is "12.34e-3". 1727 // If maximum integer digits are > 1 and are larger than 1728 // minimum integer digits, then minimum integer digits are 1729 // ignored. 1730 int exponent = digitList.decimalAt; 1731 int repeat = maxIntDigits; 1732 int minimumIntegerDigits = minIntDigits; 1733 if (repeat > 1 && repeat > minIntDigits) { 1734 // A repeating range is defined; adjust to it as follows. 1735 // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3; 1736 // -3,-4,-5=>-6, etc. This takes into account that the 1737 // exponent we have here is off by one from what we expect; 1738 // it is for the format 0.MMMMMx10^n. 1739 if (exponent >= 1) { 1740 exponent = ((exponent - 1) / repeat) * repeat; 1741 } else { 1742 // integer division rounds towards 0 1743 exponent = ((exponent - repeat) / repeat) * repeat; 1744 } 1745 minimumIntegerDigits = 1; 1746 } else { 1747 // No repeating range is defined; use minimum integer digits. 1748 exponent -= minimumIntegerDigits; 1749 } 1750 1751 // We now output a minimum number of digits, and more if there 1752 // are more digits, up to the maximum number of digits. We 1753 // place the decimal point after the "integer" digits, which 1754 // are the first (decimalAt - exponent) digits. 1755 int minimumDigits = minIntDigits + minFraDigits; 1756 if (minimumDigits < 0) { // overflow? 1757 minimumDigits = Integer.MAX_VALUE; 1758 } 1759 1760 // The number of integer digits is handled specially if the number 1761 // is zero, since then there may be no digits. 1762 int integerDigits = digitList.isZero() ? minimumIntegerDigits : 1763 digitList.decimalAt - exponent; 1764 if (minimumDigits < integerDigits) { 1765 minimumDigits = integerDigits; 1766 } 1767 int totalDigits = digitList.count; 1768 if (minimumDigits > totalDigits) { 1769 totalDigits = minimumDigits; 1770 } 1771 boolean addedDecimalSeparator = false; 1772 1773 for (int i=0; i<totalDigits; ++i) { 1774 if (i == integerDigits) { 1775 // Record field information for caller. 1776 iFieldEnd = result.length(); 1777 1778 result.append(decimal); 1779 addedDecimalSeparator = true; 1780 1781 // Record field information for caller. 1782 fFieldStart = result.length(); 1783 } 1784 result.append((i < digitList.count) ? 1785 (char)(digitList.digits[i] + zeroDelta) : 1786 zero); 1787 } 1788 1789 if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) { 1790 // Record field information for caller. 1791 iFieldEnd = result.length(); 1792 1793 result.append(decimal); 1794 addedDecimalSeparator = true; 1795 1796 // Record field information for caller. 1797 fFieldStart = result.length(); 1798 } 1799 1800 // Record field information 1801 if (iFieldEnd == -1) { 1802 iFieldEnd = result.length(); 1803 } 1804 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, 1805 iFieldStart, iFieldEnd, result); 1806 if (addedDecimalSeparator) { 1807 delegate.formatted(Field.DECIMAL_SEPARATOR, 1808 Field.DECIMAL_SEPARATOR, 1809 iFieldEnd, fFieldStart, result); 1810 } 1811 if (fFieldStart == -1) { 1812 fFieldStart = result.length(); 1813 } 1814 delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION, 1815 fFieldStart, result.length(), result); 1816 1817 // The exponent is output using the pattern-specified minimum 1818 // exponent digits. There is no maximum limit to the exponent 1819 // digits, since truncating the exponent would result in an 1820 // unacceptable inaccuracy. 1821 int fieldStart = result.length(); 1822 1823 result.append(symbols.getExponentSeparator()); 1824 1825 delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL, 1826 fieldStart, result.length(), result); 1827 1828 // For zero values, we force the exponent to zero. We 1829 // must do this here, and not earlier, because the value 1830 // is used to determine integer digit count above. 1831 if (digitList.isZero()) { 1832 exponent = 0; 1833 } 1834 1835 boolean negativeExponent = exponent < 0; 1836 if (negativeExponent) { 1837 exponent = -exponent; 1838 fieldStart = result.length(); 1839 result.append(symbols.getMinusSign()); 1840 delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN, 1841 fieldStart, result.length(), result); 1842 } 1843 digitList.set(negativeExponent, exponent); 1844 1845 int eFieldStart = result.length(); 1846 1847 for (int i=digitList.decimalAt; i<minExponentDigits; ++i) { 1848 result.append(zero); 1849 } 1850 for (int i=0; i<digitList.decimalAt; ++i) { 1851 result.append((i < digitList.count) ? 1852 (char)(digitList.digits[i] + zeroDelta) : zero); 1853 } 1854 delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart, 1855 result.length(), result); 1856 } else { 1857 int iFieldStart = result.length(); 1858 1859 // Output the integer portion. Here 'count' is the total 1860 // number of integer digits we will display, including both 1861 // leading zeros required to satisfy getMinimumIntegerDigits, 1862 // and actual digits present in the number. 1863 int count = minIntDigits; 1864 int digitIndex = 0; // Index into digitList.fDigits[] 1865 if (digitList.decimalAt > 0 && count < digitList.decimalAt) { 1866 count = digitList.decimalAt; 1867 } 1868 1869 // Handle the case where getMaximumIntegerDigits() is smaller 1870 // than the real number of integer digits. If this is so, we 1871 // output the least significant max integer digits. For example, 1872 // the value 1997 printed with 2 max integer digits is just "97". 1873 if (count > maxIntDigits) { 1874 count = maxIntDigits; 1875 digitIndex = digitList.decimalAt - count; 1876 } 1877 1878 int sizeBeforeIntegerPart = result.length(); 1879 for (int i=count-1; i>=0; --i) { 1880 if (i < digitList.decimalAt && digitIndex < digitList.count) { 1881 // Output a real digit 1882 result.append((char)(digitList.digits[digitIndex++] + zeroDelta)); 1883 } else { 1884 // Output a leading zero 1885 result.append(zero); 1886 } 1887 1888 // Output grouping separator if necessary. Don't output a 1889 // grouping separator if i==0 though; that's at the end of 1890 // the integer part. 1891 if (isGroupingUsed() && i>0 && (groupingSize != 0) && 1892 (i % groupingSize == 0)) { 1893 int gStart = result.length(); 1894 result.append(grouping); 1895 delegate.formatted(Field.GROUPING_SEPARATOR, 1896 Field.GROUPING_SEPARATOR, gStart, 1897 result.length(), result); 1898 } 1899 } 1900 1901 // Determine whether or not there are any printable fractional 1902 // digits. If we've used up the digits we know there aren't. 1903 boolean fractionPresent = (minFraDigits > 0) || 1904 (!isInteger && digitIndex < digitList.count); 1905 1906 // If there is no fraction present, and we haven't printed any 1907 // integer digits, then print a zero. Otherwise we won't print 1908 // _any_ digits, and we won't be able to parse this string. 1909 if (!fractionPresent && result.length() == sizeBeforeIntegerPart) { 1910 result.append(zero); 1911 } 1912 1913 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, 1914 iFieldStart, result.length(), result); 1915 1916 // Output the decimal separator if we always do so. 1917 int sStart = result.length(); 1918 if (decimalSeparatorAlwaysShown || fractionPresent) { 1919 result.append(decimal); 1920 } 1921 1922 if (sStart != result.length()) { 1923 delegate.formatted(Field.DECIMAL_SEPARATOR, 1924 Field.DECIMAL_SEPARATOR, 1925 sStart, result.length(), result); 1926 } 1927 int fFieldStart = result.length(); 1928 1929 for (int i=0; i < maxFraDigits; ++i) { 1930 // Here is where we escape from the loop. We escape if we've 1931 // output the maximum fraction digits (specified in the for 1932 // expression above). 1933 // We also stop when we've output the minimum digits and either: 1934 // we have an integer, so there is no fractional stuff to 1935 // display, or we're out of significant digits. 1936 if (i >= minFraDigits && 1937 (isInteger || digitIndex >= digitList.count)) { 1938 break; 1939 } 1940 1941 // Output leading fractional zeros. These are zeros that come 1942 // after the decimal but before any significant digits. These 1943 // are only output if abs(number being formatted) < 1.0. 1944 if (-1-i > (digitList.decimalAt-1)) { 1945 result.append(zero); 1946 continue; 1947 } 1948 1949 // Output a digit, if we have any precision left, or a 1950 // zero if we don't. We don't want to output noise digits. 1951 if (!isInteger && digitIndex < digitList.count) { 1952 result.append((char)(digitList.digits[digitIndex++] + zeroDelta)); 1953 } else { 1954 result.append(zero); 1955 } 1956 } 1957 1958 // Record field information for caller. 1959 delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION, 1960 fFieldStart, result.length(), result); 1961 } 1962 1963 if (isNegative) { 1964 append(result, negativeSuffix, delegate, 1965 getNegativeSuffixFieldPositions(), Field.SIGN); 1966 } else { 1967 append(result, positiveSuffix, delegate, 1968 getPositiveSuffixFieldPositions(), Field.SIGN); 1969 } 1970 1971 return result; 1972 } 1973 1974 /** 1975 * Appends the String <code>string</code> to <code>result</code>. 1976 * <code>delegate</code> is notified of all the 1977 * <code>FieldPosition</code>s in <code>positions</code>. 1978 * <p> 1979 * If one of the <code>FieldPosition</code>s in <code>positions</code> 1980 * identifies a <code>SIGN</code> attribute, it is mapped to 1981 * <code>signAttribute</code>. This is used 1982 * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code> 1983 * attribute as necessary. 1984 * <p> 1985 * This is used by <code>subformat</code> to add the prefix/suffix. 1986 */ 1987 private void append(StringBuffer result, String string, 1988 FieldDelegate delegate, 1989 FieldPosition[] positions, 1990 Format.Field signAttribute) { 1991 int start = result.length(); 1992 1993 if (string.length() > 0) { 1994 result.append(string); 1995 for (int counter = 0, max = positions.length; counter < max; 1996 counter++) { 1997 FieldPosition fp = positions[counter]; 1998 Format.Field attribute = fp.getFieldAttribute(); 1999 2000 if (attribute == Field.SIGN) { 2001 attribute = signAttribute; 2002 } 2003 delegate.formatted(attribute, attribute, 2004 start + fp.getBeginIndex(), 2005 start + fp.getEndIndex(), result); 2006 } 2007 } 2008 } 2009 2010 /** 2011 * Parses text from a string to produce a <code>Number</code>. 2012 * <p> 2013 * The method attempts to parse text starting at the index given by 2014 * <code>pos</code>. 2015 * If parsing succeeds, then the index of <code>pos</code> is updated 2016 * to the index after the last character used (parsing does not necessarily 2017 * use all characters up to the end of the string), and the parsed 2018 * number is returned. The updated <code>pos</code> can be used to 2019 * indicate the starting point for the next call to this method. 2020 * If an error occurs, then the index of <code>pos</code> is not 2021 * changed, the error index of <code>pos</code> is set to the index of 2022 * the character where the error occurred, and null is returned. 2023 * <p> 2024 * The subclass returned depends on the value of {@link #isParseBigDecimal} 2025 * as well as on the string being parsed. 2026 * <ul> 2027 * <li>If <code>isParseBigDecimal()</code> is false (the default), 2028 * most integer values are returned as <code>Long</code> 2029 * objects, no matter how they are written: <code>"17"</code> and 2030 * <code>"17.000"</code> both parse to <code>Long(17)</code>. 2031 * Values that cannot fit into a <code>Long</code> are returned as 2032 * <code>Double</code>s. This includes values with a fractional part, 2033 * infinite values, <code>NaN</code>, and the value -0.0. 2034 * <code>DecimalFormat</code> does <em>not</em> decide whether to 2035 * return a <code>Double</code> or a <code>Long</code> based on the 2036 * presence of a decimal separator in the source string. Doing so 2037 * would prevent integers that overflow the mantissa of a double, 2038 * such as <code>"-9,223,372,036,854,775,808.00"</code>, from being 2039 * parsed accurately. 2040 * <p> 2041 * Callers may use the <code>Number</code> methods 2042 * <code>doubleValue</code>, <code>longValue</code>, etc., to obtain 2043 * the type they want. 2044 * <li>If <code>isParseBigDecimal()</code> is true, values are returned 2045 * as <code>BigDecimal</code> objects. The values are the ones 2046 * constructed by {@link java.math.BigDecimal#BigDecimal(String)} 2047 * for corresponding strings in locale-independent format. The 2048 * special cases negative and positive infinity and NaN are returned 2049 * as <code>Double</code> instances holding the values of the 2050 * corresponding <code>Double</code> constants. 2051 * </ul> 2052 * <p> 2053 * <code>DecimalFormat</code> parses all Unicode characters that represent 2054 * decimal digits, as defined by <code>Character.digit()</code>. In 2055 * addition, <code>DecimalFormat</code> also recognizes as digits the ten 2056 * consecutive characters starting with the localized zero digit defined in 2057 * the <code>DecimalFormatSymbols</code> object. 2058 * 2059 * @param text the string to be parsed 2060 * @param pos A <code>ParsePosition</code> object with index and error 2061 * index information as described above. 2062 * @return the parsed value, or <code>null</code> if the parse fails 2063 * @exception NullPointerException if <code>text</code> or 2064 * <code>pos</code> is null. 2065 */ 2066 @Override 2067 public Number parse(String text, ParsePosition pos) { 2068 // special case NaN 2069 if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) { 2070 pos.index = pos.index + symbols.getNaN().length(); 2071 return Double.valueOf(Double.NaN); 2072 } 2073 2074 boolean[] status = new boolean[STATUS_LENGTH]; 2075 if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) { 2076 return null; 2077 } 2078 2079 // special case INFINITY 2080 if (status[STATUS_INFINITE]) { 2081 if (status[STATUS_POSITIVE] == (multiplier >= 0)) { 2082 return Double.valueOf(Double.POSITIVE_INFINITY); 2083 } else { 2084 return Double.valueOf(Double.NEGATIVE_INFINITY); 2085 } 2086 } 2087 2088 if (multiplier == 0) { 2089 if (digitList.isZero()) { 2090 return Double.valueOf(Double.NaN); 2091 } else if (status[STATUS_POSITIVE]) { 2092 return Double.valueOf(Double.POSITIVE_INFINITY); 2093 } else { 2094 return Double.valueOf(Double.NEGATIVE_INFINITY); 2095 } 2096 } 2097 2098 if (isParseBigDecimal()) { 2099 BigDecimal bigDecimalResult = digitList.getBigDecimal(); 2100 2101 if (multiplier != 1) { 2102 try { 2103 bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier()); 2104 } 2105 catch (ArithmeticException e) { // non-terminating decimal expansion 2106 bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode); 2107 } 2108 } 2109 2110 if (!status[STATUS_POSITIVE]) { 2111 bigDecimalResult = bigDecimalResult.negate(); 2112 } 2113 return bigDecimalResult; 2114 } else { 2115 boolean gotDouble = true; 2116 boolean gotLongMinimum = false; 2117 double doubleResult = 0.0; 2118 long longResult = 0; 2119 2120 // Finally, have DigitList parse the digits into a value. 2121 if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) { 2122 gotDouble = false; 2123 longResult = digitList.getLong(); 2124 if (longResult < 0) { // got Long.MIN_VALUE 2125 gotLongMinimum = true; 2126 } 2127 } else { 2128 doubleResult = digitList.getDouble(); 2129 } 2130 2131 // Divide by multiplier. We have to be careful here not to do 2132 // unneeded conversions between double and long. 2133 if (multiplier != 1) { 2134 if (gotDouble) { 2135 doubleResult /= multiplier; 2136 } else { 2137 // Avoid converting to double if we can 2138 if (longResult % multiplier == 0) { 2139 longResult /= multiplier; 2140 } else { 2141 doubleResult = ((double)longResult) / multiplier; 2142 gotDouble = true; 2143 } 2144 } 2145 } 2146 2147 if (!status[STATUS_POSITIVE] && !gotLongMinimum) { 2148 doubleResult = -doubleResult; 2149 longResult = -longResult; 2150 } 2151 2152 // At this point, if we divided the result by the multiplier, the 2153 // result may fit into a long. We check for this case and return 2154 // a long if possible. 2155 // We must do this AFTER applying the negative (if appropriate) 2156 // in order to handle the case of LONG_MIN; otherwise, if we do 2157 // this with a positive value -LONG_MIN, the double is > 0, but 2158 // the long is < 0. We also must retain a double in the case of 2159 // -0.0, which will compare as == to a long 0 cast to a double 2160 // (bug 4162852). 2161 if (multiplier != 1 && gotDouble) { 2162 longResult = (long)doubleResult; 2163 gotDouble = ((doubleResult != (double)longResult) || 2164 (doubleResult == 0.0 && 1/doubleResult < 0.0)) && 2165 !isParseIntegerOnly(); 2166 } 2167 2168 // cast inside of ?: because of binary numeric promotion, JLS 15.25 2169 return gotDouble ? (Number)doubleResult : (Number)longResult; 2170 } 2171 } 2172 2173 /** 2174 * Return a BigInteger multiplier. 2175 */ 2176 private BigInteger getBigIntegerMultiplier() { 2177 if (bigIntegerMultiplier == null) { 2178 bigIntegerMultiplier = BigInteger.valueOf(multiplier); 2179 } 2180 return bigIntegerMultiplier; 2181 } 2182 private transient BigInteger bigIntegerMultiplier; 2183 2184 /** 2185 * Return a BigDecimal multiplier. 2186 */ 2187 private BigDecimal getBigDecimalMultiplier() { 2188 if (bigDecimalMultiplier == null) { 2189 bigDecimalMultiplier = new BigDecimal(multiplier); 2190 } 2191 return bigDecimalMultiplier; 2192 } 2193 private transient BigDecimal bigDecimalMultiplier; 2194 2195 private static final int STATUS_INFINITE = 0; 2196 private static final int STATUS_POSITIVE = 1; 2197 private static final int STATUS_LENGTH = 2; 2198 2199 /** 2200 * Parse the given text into a number. The text is parsed beginning at 2201 * parsePosition, until an unparseable character is seen. 2202 * @param text The string to parse. 2203 * @param parsePosition The position at which to being parsing. Upon 2204 * return, the first unparseable character. 2205 * @param digits The DigitList to set to the parsed value. 2206 * @param isExponent If true, parse an exponent. This means no 2207 * infinite values and integer only. 2208 * @param status Upon return contains boolean status flags indicating 2209 * whether the value was infinite and whether it was positive. 2210 */ 2211 private final boolean subparse(String text, ParsePosition parsePosition, 2212 String positivePrefix, String negativePrefix, 2213 DigitList digits, boolean isExponent, 2214 boolean status[]) { 2215 int position = parsePosition.index; 2216 int oldStart = parsePosition.index; 2217 int backup; 2218 boolean gotPositive, gotNegative; 2219 2220 // check for positivePrefix; take longest 2221 gotPositive = text.regionMatches(position, positivePrefix, 0, 2222 positivePrefix.length()); 2223 gotNegative = text.regionMatches(position, negativePrefix, 0, 2224 negativePrefix.length()); 2225 2226 if (gotPositive && gotNegative) { 2227 if (positivePrefix.length() > negativePrefix.length()) { 2228 gotNegative = false; 2229 } else if (positivePrefix.length() < negativePrefix.length()) { 2230 gotPositive = false; 2231 } 2232 } 2233 2234 if (gotPositive) { 2235 position += positivePrefix.length(); 2236 } else if (gotNegative) { 2237 position += negativePrefix.length(); 2238 } else { 2239 parsePosition.errorIndex = position; 2240 return false; 2241 } 2242 2243 // process digits or Inf, find decimal position 2244 status[STATUS_INFINITE] = false; 2245 if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0, 2246 symbols.getInfinity().length())) { 2247 position += symbols.getInfinity().length(); 2248 status[STATUS_INFINITE] = true; 2249 } else { 2250 // We now have a string of digits, possibly with grouping symbols, 2251 // and decimal points. We want to process these into a DigitList. 2252 // We don't want to put a bunch of leading zeros into the DigitList 2253 // though, so we keep track of the location of the decimal point, 2254 // put only significant digits into the DigitList, and adjust the 2255 // exponent as needed. 2256 2257 digits.decimalAt = digits.count = 0; 2258 char zero = symbols.getZeroDigit(); 2259 char decimal = isCurrencyFormat ? 2260 symbols.getMonetaryDecimalSeparator() : 2261 symbols.getDecimalSeparator(); 2262 char grouping = symbols.getGroupingSeparator(); 2263 String exponentString = symbols.getExponentSeparator(); 2264 boolean sawDecimal = false; 2265 boolean sawExponent = false; 2266 boolean sawDigit = false; 2267 int exponent = 0; // Set to the exponent value, if any 2268 2269 // We have to track digitCount ourselves, because digits.count will 2270 // pin when the maximum allowable digits is reached. 2271 int digitCount = 0; 2272 2273 backup = -1; 2274 for (; position < text.length(); ++position) { 2275 char ch = text.charAt(position); 2276 2277 /* We recognize all digit ranges, not only the Latin digit range 2278 * '0'..'9'. We do so by using the Character.digit() method, 2279 * which converts a valid Unicode digit to the range 0..9. 2280 * 2281 * The character 'ch' may be a digit. If so, place its value 2282 * from 0 to 9 in 'digit'. First try using the locale digit, 2283 * which may or MAY NOT be a standard Unicode digit range. If 2284 * this fails, try using the standard Unicode digit ranges by 2285 * calling Character.digit(). If this also fails, digit will 2286 * have a value outside the range 0..9. 2287 */ 2288 int digit = ch - zero; 2289 if (digit < 0 || digit > 9) { 2290 digit = Character.digit(ch, 10); 2291 } 2292 2293 if (digit == 0) { 2294 // Cancel out backup setting (see grouping handler below) 2295 backup = -1; // Do this BEFORE continue statement below!!! 2296 sawDigit = true; 2297 2298 // Handle leading zeros 2299 if (digits.count == 0) { 2300 // Ignore leading zeros in integer part of number. 2301 if (!sawDecimal) { 2302 continue; 2303 } 2304 2305 // If we have seen the decimal, but no significant 2306 // digits yet, then we account for leading zeros by 2307 // decrementing the digits.decimalAt into negative 2308 // values. 2309 --digits.decimalAt; 2310 } else { 2311 ++digitCount; 2312 digits.append((char)(digit + '0')); 2313 } 2314 } else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above 2315 sawDigit = true; 2316 ++digitCount; 2317 digits.append((char)(digit + '0')); 2318 2319 // Cancel out backup setting (see grouping handler below) 2320 backup = -1; 2321 } else if (!isExponent && ch == decimal) { 2322 // If we're only parsing integers, or if we ALREADY saw the 2323 // decimal, then don't parse this one. 2324 if (isParseIntegerOnly() || sawDecimal) { 2325 break; 2326 } 2327 digits.decimalAt = digitCount; // Not digits.count! 2328 sawDecimal = true; 2329 } else if (!isExponent && ch == grouping && isGroupingUsed()) { 2330 if (sawDecimal) { 2331 break; 2332 } 2333 // Ignore grouping characters, if we are using them, but 2334 // require that they be followed by a digit. Otherwise 2335 // we backup and reprocess them. 2336 backup = position; 2337 } else if (!isExponent && text.regionMatches(position, exponentString, 0, exponentString.length()) 2338 && !sawExponent) { 2339 // Process the exponent by recursively calling this method. 2340 ParsePosition pos = new ParsePosition(position + exponentString.length()); 2341 boolean[] stat = new boolean[STATUS_LENGTH]; 2342 DigitList exponentDigits = new DigitList(); 2343 2344 if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) && 2345 exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) { 2346 position = pos.index; // Advance past the exponent 2347 exponent = (int)exponentDigits.getLong(); 2348 if (!stat[STATUS_POSITIVE]) { 2349 exponent = -exponent; 2350 } 2351 sawExponent = true; 2352 } 2353 break; // Whether we fail or succeed, we exit this loop 2354 } else { 2355 break; 2356 } 2357 } 2358 2359 if (backup != -1) { 2360 position = backup; 2361 } 2362 2363 // If there was no decimal point we have an integer 2364 if (!sawDecimal) { 2365 digits.decimalAt = digitCount; // Not digits.count! 2366 } 2367 2368 // Adjust for exponent, if any 2369 digits.decimalAt += exponent; 2370 2371 // If none of the text string was recognized. For example, parse 2372 // "x" with pattern "#0.00" (return index and error index both 0) 2373 // parse "$" with pattern "$#0.00". (return index 0 and error 2374 // index 1). 2375 if (!sawDigit && digitCount == 0) { 2376 parsePosition.index = oldStart; 2377 parsePosition.errorIndex = oldStart; 2378 return false; 2379 } 2380 } 2381 2382 // check for suffix 2383 if (!isExponent) { 2384 if (gotPositive) { 2385 gotPositive = text.regionMatches(position,positiveSuffix,0, 2386 positiveSuffix.length()); 2387 } 2388 if (gotNegative) { 2389 gotNegative = text.regionMatches(position,negativeSuffix,0, 2390 negativeSuffix.length()); 2391 } 2392 2393 // if both match, take longest 2394 if (gotPositive && gotNegative) { 2395 if (positiveSuffix.length() > negativeSuffix.length()) { 2396 gotNegative = false; 2397 } else if (positiveSuffix.length() < negativeSuffix.length()) { 2398 gotPositive = false; 2399 } 2400 } 2401 2402 // fail if neither or both 2403 if (gotPositive == gotNegative) { 2404 parsePosition.errorIndex = position; 2405 return false; 2406 } 2407 2408 parsePosition.index = position + 2409 (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success! 2410 } else { 2411 parsePosition.index = position; 2412 } 2413 2414 status[STATUS_POSITIVE] = gotPositive; 2415 if (parsePosition.index == oldStart) { 2416 parsePosition.errorIndex = position; 2417 return false; 2418 } 2419 return true; 2420 } 2421 2422 /** 2423 * Returns a copy of the decimal format symbols, which is generally not 2424 * changed by the programmer or user. 2425 * @return a copy of the desired DecimalFormatSymbols 2426 * @see java.text.DecimalFormatSymbols 2427 */ 2428 public DecimalFormatSymbols getDecimalFormatSymbols() { 2429 try { 2430 // don't allow multiple references 2431 return (DecimalFormatSymbols) symbols.clone(); 2432 } catch (Exception foo) { 2433 return null; // should never happen 2434 } 2435 } 2436 2437 2438 /** 2439 * Sets the decimal format symbols, which is generally not changed 2440 * by the programmer or user. 2441 * @param newSymbols desired DecimalFormatSymbols 2442 * @see java.text.DecimalFormatSymbols 2443 */ 2444 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { 2445 try { 2446 // don't allow multiple references 2447 symbols = (DecimalFormatSymbols) newSymbols.clone(); 2448 expandAffixes(); 2449 fastPathCheckNeeded = true; 2450 } catch (Exception foo) { 2451 // should never happen 2452 } 2453 } 2454 2455 /** 2456 * Get the positive prefix. 2457 * <P>Examples: +123, $123, sFr123 2458 * 2459 * @return the positive prefix 2460 */ 2461 public String getPositivePrefix () { 2462 return positivePrefix; 2463 } 2464 2465 /** 2466 * Set the positive prefix. 2467 * <P>Examples: +123, $123, sFr123 2468 * 2469 * @param newValue the new positive prefix 2470 */ 2471 public void setPositivePrefix (String newValue) { 2472 positivePrefix = newValue; 2473 posPrefixPattern = null; 2474 positivePrefixFieldPositions = null; 2475 fastPathCheckNeeded = true; 2476 } 2477 2478 /** 2479 * Returns the FieldPositions of the fields in the prefix used for 2480 * positive numbers. This is not used if the user has explicitly set 2481 * a positive prefix via <code>setPositivePrefix</code>. This is 2482 * lazily created. 2483 * 2484 * @return FieldPositions in positive prefix 2485 */ 2486 private FieldPosition[] getPositivePrefixFieldPositions() { 2487 if (positivePrefixFieldPositions == null) { 2488 if (posPrefixPattern != null) { 2489 positivePrefixFieldPositions = expandAffix(posPrefixPattern); 2490 } else { 2491 positivePrefixFieldPositions = EmptyFieldPositionArray; 2492 } 2493 } 2494 return positivePrefixFieldPositions; 2495 } 2496 2497 /** 2498 * Get the negative prefix. 2499 * <P>Examples: -123, ($123) (with negative suffix), sFr-123 2500 * 2501 * @return the negative prefix 2502 */ 2503 public String getNegativePrefix () { 2504 return negativePrefix; 2505 } 2506 2507 /** 2508 * Set the negative prefix. 2509 * <P>Examples: -123, ($123) (with negative suffix), sFr-123 2510 * 2511 * @param newValue the new negative prefix 2512 */ 2513 public void setNegativePrefix (String newValue) { 2514 negativePrefix = newValue; 2515 negPrefixPattern = null; 2516 fastPathCheckNeeded = true; 2517 } 2518 2519 /** 2520 * Returns the FieldPositions of the fields in the prefix used for 2521 * negative numbers. This is not used if the user has explicitly set 2522 * a negative prefix via <code>setNegativePrefix</code>. This is 2523 * lazily created. 2524 * 2525 * @return FieldPositions in positive prefix 2526 */ 2527 private FieldPosition[] getNegativePrefixFieldPositions() { 2528 if (negativePrefixFieldPositions == null) { 2529 if (negPrefixPattern != null) { 2530 negativePrefixFieldPositions = expandAffix(negPrefixPattern); 2531 } else { 2532 negativePrefixFieldPositions = EmptyFieldPositionArray; 2533 } 2534 } 2535 return negativePrefixFieldPositions; 2536 } 2537 2538 /** 2539 * Get the positive suffix. 2540 * <P>Example: 123% 2541 * 2542 * @return the positive suffix 2543 */ 2544 public String getPositiveSuffix () { 2545 return positiveSuffix; 2546 } 2547 2548 /** 2549 * Set the positive suffix. 2550 * <P>Example: 123% 2551 * 2552 * @param newValue the new positive suffix 2553 */ 2554 public void setPositiveSuffix (String newValue) { 2555 positiveSuffix = newValue; 2556 posSuffixPattern = null; 2557 fastPathCheckNeeded = true; 2558 } 2559 2560 /** 2561 * Returns the FieldPositions of the fields in the suffix used for 2562 * positive numbers. This is not used if the user has explicitly set 2563 * a positive suffix via <code>setPositiveSuffix</code>. This is 2564 * lazily created. 2565 * 2566 * @return FieldPositions in positive prefix 2567 */ 2568 private FieldPosition[] getPositiveSuffixFieldPositions() { 2569 if (positiveSuffixFieldPositions == null) { 2570 if (posSuffixPattern != null) { 2571 positiveSuffixFieldPositions = expandAffix(posSuffixPattern); 2572 } else { 2573 positiveSuffixFieldPositions = EmptyFieldPositionArray; 2574 } 2575 } 2576 return positiveSuffixFieldPositions; 2577 } 2578 2579 /** 2580 * Get the negative suffix. 2581 * <P>Examples: -123%, ($123) (with positive suffixes) 2582 * 2583 * @return the negative suffix 2584 */ 2585 public String getNegativeSuffix () { 2586 return negativeSuffix; 2587 } 2588 2589 /** 2590 * Set the negative suffix. 2591 * <P>Examples: 123% 2592 * 2593 * @param newValue the new negative suffix 2594 */ 2595 public void setNegativeSuffix (String newValue) { 2596 negativeSuffix = newValue; 2597 negSuffixPattern = null; 2598 fastPathCheckNeeded = true; 2599 } 2600 2601 /** 2602 * Returns the FieldPositions of the fields in the suffix used for 2603 * negative numbers. This is not used if the user has explicitly set 2604 * a negative suffix via <code>setNegativeSuffix</code>. This is 2605 * lazily created. 2606 * 2607 * @return FieldPositions in positive prefix 2608 */ 2609 private FieldPosition[] getNegativeSuffixFieldPositions() { 2610 if (negativeSuffixFieldPositions == null) { 2611 if (negSuffixPattern != null) { 2612 negativeSuffixFieldPositions = expandAffix(negSuffixPattern); 2613 } else { 2614 negativeSuffixFieldPositions = EmptyFieldPositionArray; 2615 } 2616 } 2617 return negativeSuffixFieldPositions; 2618 } 2619 2620 /** 2621 * Gets the multiplier for use in percent, per mille, and similar 2622 * formats. 2623 * 2624 * @return the multiplier 2625 * @see #setMultiplier(int) 2626 */ 2627 public int getMultiplier () { 2628 return multiplier; 2629 } 2630 2631 /** 2632 * Sets the multiplier for use in percent, per mille, and similar 2633 * formats. 2634 * For a percent format, set the multiplier to 100 and the suffixes to 2635 * have '%' (for Arabic, use the Arabic percent sign). 2636 * For a per mille format, set the multiplier to 1000 and the suffixes to 2637 * have '\u2030'. 2638 * 2639 * <P>Example: with multiplier 100, 1.23 is formatted as "123", and 2640 * "123" is parsed into 1.23. 2641 * 2642 * @param newValue the new multiplier 2643 * @see #getMultiplier 2644 */ 2645 public void setMultiplier (int newValue) { 2646 multiplier = newValue; 2647 bigDecimalMultiplier = null; 2648 bigIntegerMultiplier = null; 2649 fastPathCheckNeeded = true; 2650 } 2651 2652 /** 2653 * {@inheritDoc} 2654 */ 2655 @Override 2656 public void setGroupingUsed(boolean newValue) { 2657 super.setGroupingUsed(newValue); 2658 fastPathCheckNeeded = true; 2659 } 2660 2661 /** 2662 * Return the grouping size. Grouping size is the number of digits between 2663 * grouping separators in the integer portion of a number. For example, 2664 * in the number "123,456.78", the grouping size is 3. 2665 * 2666 * @return the grouping size 2667 * @see #setGroupingSize 2668 * @see java.text.NumberFormat#isGroupingUsed 2669 * @see java.text.DecimalFormatSymbols#getGroupingSeparator 2670 */ 2671 public int getGroupingSize () { 2672 return groupingSize; 2673 } 2674 2675 /** 2676 * Set the grouping size. Grouping size is the number of digits between 2677 * grouping separators in the integer portion of a number. For example, 2678 * in the number "123,456.78", the grouping size is 3. 2679 * <br> 2680 * The value passed in is converted to a byte, which may lose information. 2681 * 2682 * @param newValue the new grouping size 2683 * @see #getGroupingSize 2684 * @see java.text.NumberFormat#setGroupingUsed 2685 * @see java.text.DecimalFormatSymbols#setGroupingSeparator 2686 */ 2687 public void setGroupingSize (int newValue) { 2688 groupingSize = (byte)newValue; 2689 fastPathCheckNeeded = true; 2690 } 2691 2692 /** 2693 * Allows you to get the behavior of the decimal separator with integers. 2694 * (The decimal separator will always appear with decimals.) 2695 * <P>Example: Decimal ON: 12345 → 12345.; OFF: 12345 → 12345 2696 * 2697 * @return {@code true} if the decimal separator is always shown; 2698 * {@code false} otherwise 2699 */ 2700 public boolean isDecimalSeparatorAlwaysShown() { 2701 return decimalSeparatorAlwaysShown; 2702 } 2703 2704 /** 2705 * Allows you to set the behavior of the decimal separator with integers. 2706 * (The decimal separator will always appear with decimals.) 2707 * <P>Example: Decimal ON: 12345 → 12345.; OFF: 12345 → 12345 2708 * 2709 * @param newValue {@code true} if the decimal separator is always shown; 2710 * {@code false} otherwise 2711 */ 2712 public void setDecimalSeparatorAlwaysShown(boolean newValue) { 2713 decimalSeparatorAlwaysShown = newValue; 2714 fastPathCheckNeeded = true; 2715 } 2716 2717 /** 2718 * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)} 2719 * method returns <code>BigDecimal</code>. The default value is false. 2720 * 2721 * @return {@code true} if the parse method returns BigDecimal; 2722 * {@code false} otherwise 2723 * @see #setParseBigDecimal 2724 * @since 1.5 2725 */ 2726 public boolean isParseBigDecimal() { 2727 return parseBigDecimal; 2728 } 2729 2730 /** 2731 * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)} 2732 * method returns <code>BigDecimal</code>. 2733 * 2734 * @param newValue {@code true} if the parse method returns BigDecimal; 2735 * {@code false} otherwise 2736 * @see #isParseBigDecimal 2737 * @since 1.5 2738 */ 2739 public void setParseBigDecimal(boolean newValue) { 2740 parseBigDecimal = newValue; 2741 } 2742 2743 /** 2744 * Standard override; no change in semantics. 2745 */ 2746 @Override 2747 public Object clone() { 2748 DecimalFormat other = (DecimalFormat) super.clone(); 2749 other.symbols = (DecimalFormatSymbols) symbols.clone(); 2750 other.digitList = (DigitList) digitList.clone(); 2751 2752 // Fast-path is almost stateless algorithm. The only logical state is the 2753 // isFastPath flag. In addition fastPathCheckNeeded is a sentinel flag 2754 // that forces recalculation of all fast-path fields when set to true. 2755 // 2756 // There is thus no need to clone all the fast-path fields. 2757 // We just only need to set fastPathCheckNeeded to true when cloning, 2758 // and init fastPathData to null as if it were a truly new instance. 2759 // Every fast-path field will be recalculated (only once) at next usage of 2760 // fast-path algorithm. 2761 other.fastPathCheckNeeded = true; 2762 other.isFastPath = false; 2763 other.fastPathData = null; 2764 2765 return other; 2766 } 2767 2768 /** 2769 * Overrides equals 2770 */ 2771 @Override 2772 public boolean equals(Object obj) 2773 { 2774 if (obj == null) 2775 return false; 2776 if (!super.equals(obj)) 2777 return false; // super does class check 2778 DecimalFormat other = (DecimalFormat) obj; 2779 return ((posPrefixPattern == other.posPrefixPattern && 2780 positivePrefix.equals(other.positivePrefix)) 2781 || (posPrefixPattern != null && 2782 posPrefixPattern.equals(other.posPrefixPattern))) 2783 && ((posSuffixPattern == other.posSuffixPattern && 2784 positiveSuffix.equals(other.positiveSuffix)) 2785 || (posSuffixPattern != null && 2786 posSuffixPattern.equals(other.posSuffixPattern))) 2787 && ((negPrefixPattern == other.negPrefixPattern && 2788 negativePrefix.equals(other.negativePrefix)) 2789 || (negPrefixPattern != null && 2790 negPrefixPattern.equals(other.negPrefixPattern))) 2791 && ((negSuffixPattern == other.negSuffixPattern && 2792 negativeSuffix.equals(other.negativeSuffix)) 2793 || (negSuffixPattern != null && 2794 negSuffixPattern.equals(other.negSuffixPattern))) 2795 && multiplier == other.multiplier 2796 && groupingSize == other.groupingSize 2797 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown 2798 && parseBigDecimal == other.parseBigDecimal 2799 && useExponentialNotation == other.useExponentialNotation 2800 && (!useExponentialNotation || 2801 minExponentDigits == other.minExponentDigits) 2802 && maximumIntegerDigits == other.maximumIntegerDigits 2803 && minimumIntegerDigits == other.minimumIntegerDigits 2804 && maximumFractionDigits == other.maximumFractionDigits 2805 && minimumFractionDigits == other.minimumFractionDigits 2806 && roundingMode == other.roundingMode 2807 && symbols.equals(other.symbols); 2808 } 2809 2810 /** 2811 * Overrides hashCode 2812 */ 2813 @Override 2814 public int hashCode() { 2815 return super.hashCode() * 37 + positivePrefix.hashCode(); 2816 // just enough fields for a reasonable distribution 2817 } 2818 2819 /** 2820 * Synthesizes a pattern string that represents the current state 2821 * of this Format object. 2822 * 2823 * @return a pattern string 2824 * @see #applyPattern 2825 */ 2826 public String toPattern() { 2827 return toPattern( false ); 2828 } 2829 2830 /** 2831 * Synthesizes a localized pattern string that represents the current 2832 * state of this Format object. 2833 * 2834 * @return a localized pattern string 2835 * @see #applyPattern 2836 */ 2837 public String toLocalizedPattern() { 2838 return toPattern( true ); 2839 } 2840 2841 /** 2842 * Expand the affix pattern strings into the expanded affix strings. If any 2843 * affix pattern string is null, do not expand it. This method should be 2844 * called any time the symbols or the affix patterns change in order to keep 2845 * the expanded affix strings up to date. 2846 */ 2847 private void expandAffixes() { 2848 // Reuse one StringBuffer for better performance 2849 StringBuffer buffer = new StringBuffer(); 2850 if (posPrefixPattern != null) { 2851 positivePrefix = expandAffix(posPrefixPattern, buffer); 2852 positivePrefixFieldPositions = null; 2853 } 2854 if (posSuffixPattern != null) { 2855 positiveSuffix = expandAffix(posSuffixPattern, buffer); 2856 positiveSuffixFieldPositions = null; 2857 } 2858 if (negPrefixPattern != null) { 2859 negativePrefix = expandAffix(negPrefixPattern, buffer); 2860 negativePrefixFieldPositions = null; 2861 } 2862 if (negSuffixPattern != null) { 2863 negativeSuffix = expandAffix(negSuffixPattern, buffer); 2864 negativeSuffixFieldPositions = null; 2865 } 2866 } 2867 2868 /** 2869 * Expand an affix pattern into an affix string. All characters in the 2870 * pattern are literal unless prefixed by QUOTE. The following characters 2871 * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, 2872 * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE + 2873 * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217 2874 * currency code. Any other character after a QUOTE represents itself. 2875 * QUOTE must be followed by another character; QUOTE may not occur by 2876 * itself at the end of the pattern. 2877 * 2878 * @param pattern the non-null, possibly empty pattern 2879 * @param buffer a scratch StringBuffer; its contents will be lost 2880 * @return the expanded equivalent of pattern 2881 */ 2882 private String expandAffix(String pattern, StringBuffer buffer) { 2883 buffer.setLength(0); 2884 for (int i=0; i<pattern.length(); ) { 2885 char c = pattern.charAt(i++); 2886 if (c == QUOTE) { 2887 c = pattern.charAt(i++); 2888 switch (c) { 2889 case CURRENCY_SIGN: 2890 if (i<pattern.length() && 2891 pattern.charAt(i) == CURRENCY_SIGN) { 2892 ++i; 2893 buffer.append(symbols.getInternationalCurrencySymbol()); 2894 } else { 2895 buffer.append(symbols.getCurrencySymbol()); 2896 } 2897 continue; 2898 case PATTERN_PERCENT: 2899 c = symbols.getPercent(); 2900 break; 2901 case PATTERN_PER_MILLE: 2902 c = symbols.getPerMill(); 2903 break; 2904 case PATTERN_MINUS: 2905 c = symbols.getMinusSign(); 2906 break; 2907 } 2908 } 2909 buffer.append(c); 2910 } 2911 return buffer.toString(); 2912 } 2913 2914 /** 2915 * Expand an affix pattern into an array of FieldPositions describing 2916 * how the pattern would be expanded. 2917 * All characters in the 2918 * pattern are literal unless prefixed by QUOTE. The following characters 2919 * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, 2920 * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE + 2921 * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217 2922 * currency code. Any other character after a QUOTE represents itself. 2923 * QUOTE must be followed by another character; QUOTE may not occur by 2924 * itself at the end of the pattern. 2925 * 2926 * @param pattern the non-null, possibly empty pattern 2927 * @return FieldPosition array of the resulting fields. 2928 */ 2929 private FieldPosition[] expandAffix(String pattern) { 2930 ArrayList<FieldPosition> positions = null; 2931 int stringIndex = 0; 2932 for (int i=0; i<pattern.length(); ) { 2933 char c = pattern.charAt(i++); 2934 if (c == QUOTE) { 2935 int field = -1; 2936 Format.Field fieldID = null; 2937 c = pattern.charAt(i++); 2938 switch (c) { 2939 case CURRENCY_SIGN: 2940 String string; 2941 if (i<pattern.length() && 2942 pattern.charAt(i) == CURRENCY_SIGN) { 2943 ++i; 2944 string = symbols.getInternationalCurrencySymbol(); 2945 } else { 2946 string = symbols.getCurrencySymbol(); 2947 } 2948 if (string.length() > 0) { 2949 if (positions == null) { 2950 positions = new ArrayList<>(2); 2951 } 2952 FieldPosition fp = new FieldPosition(Field.CURRENCY); 2953 fp.setBeginIndex(stringIndex); 2954 fp.setEndIndex(stringIndex + string.length()); 2955 positions.add(fp); 2956 stringIndex += string.length(); 2957 } 2958 continue; 2959 case PATTERN_PERCENT: 2960 c = symbols.getPercent(); 2961 field = -1; 2962 fieldID = Field.PERCENT; 2963 break; 2964 case PATTERN_PER_MILLE: 2965 c = symbols.getPerMill(); 2966 field = -1; 2967 fieldID = Field.PERMILLE; 2968 break; 2969 case PATTERN_MINUS: 2970 c = symbols.getMinusSign(); 2971 field = -1; 2972 fieldID = Field.SIGN; 2973 break; 2974 } 2975 if (fieldID != null) { 2976 if (positions == null) { 2977 positions = new ArrayList<>(2); 2978 } 2979 FieldPosition fp = new FieldPosition(fieldID, field); 2980 fp.setBeginIndex(stringIndex); 2981 fp.setEndIndex(stringIndex + 1); 2982 positions.add(fp); 2983 } 2984 } 2985 stringIndex++; 2986 } 2987 if (positions != null) { 2988 return positions.toArray(EmptyFieldPositionArray); 2989 } 2990 return EmptyFieldPositionArray; 2991 } 2992 2993 /** 2994 * Appends an affix pattern to the given StringBuffer, quoting special 2995 * characters as needed. Uses the internal affix pattern, if that exists, 2996 * or the literal affix, if the internal affix pattern is null. The 2997 * appended string will generate the same affix pattern (or literal affix) 2998 * when passed to toPattern(). 2999 * 3000 * @param buffer the affix string is appended to this 3001 * @param affixPattern a pattern such as posPrefixPattern; may be null 3002 * @param expAffix a corresponding expanded affix, such as positivePrefix. 3003 * Ignored unless affixPattern is null. If affixPattern is null, then 3004 * expAffix is appended as a literal affix. 3005 * @param localized true if the appended pattern should contain localized 3006 * pattern characters; otherwise, non-localized pattern chars are appended 3007 */ 3008 private void appendAffix(StringBuffer buffer, String affixPattern, 3009 String expAffix, boolean localized) { 3010 if (affixPattern == null) { 3011 appendAffix(buffer, expAffix, localized); 3012 } else { 3013 int i; 3014 for (int pos=0; pos<affixPattern.length(); pos=i) { 3015 i = affixPattern.indexOf(QUOTE, pos); 3016 if (i < 0) { 3017 appendAffix(buffer, affixPattern.substring(pos), localized); 3018 break; 3019 } 3020 if (i > pos) { 3021 appendAffix(buffer, affixPattern.substring(pos, i), localized); 3022 } 3023 char c = affixPattern.charAt(++i); 3024 ++i; 3025 if (c == QUOTE) { 3026 buffer.append(c); 3027 // Fall through and append another QUOTE below 3028 } else if (c == CURRENCY_SIGN && 3029 i<affixPattern.length() && 3030 affixPattern.charAt(i) == CURRENCY_SIGN) { 3031 ++i; 3032 buffer.append(c); 3033 // Fall through and append another CURRENCY_SIGN below 3034 } else if (localized) { 3035 switch (c) { 3036 case PATTERN_PERCENT: 3037 c = symbols.getPercent(); 3038 break; 3039 case PATTERN_PER_MILLE: 3040 c = symbols.getPerMill(); 3041 break; 3042 case PATTERN_MINUS: 3043 c = symbols.getMinusSign(); 3044 break; 3045 } 3046 } 3047 buffer.append(c); 3048 } 3049 } 3050 } 3051 3052 /** 3053 * Append an affix to the given StringBuffer, using quotes if 3054 * there are special characters. Single quotes themselves must be 3055 * escaped in either case. 3056 */ 3057 private void appendAffix(StringBuffer buffer, String affix, boolean localized) { 3058 boolean needQuote; 3059 if (localized) { 3060 needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0 3061 || affix.indexOf(symbols.getGroupingSeparator()) >= 0 3062 || affix.indexOf(symbols.getDecimalSeparator()) >= 0 3063 || affix.indexOf(symbols.getPercent()) >= 0 3064 || affix.indexOf(symbols.getPerMill()) >= 0 3065 || affix.indexOf(symbols.getDigit()) >= 0 3066 || affix.indexOf(symbols.getPatternSeparator()) >= 0 3067 || affix.indexOf(symbols.getMinusSign()) >= 0 3068 || affix.indexOf(CURRENCY_SIGN) >= 0; 3069 } else { 3070 needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0 3071 || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0 3072 || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0 3073 || affix.indexOf(PATTERN_PERCENT) >= 0 3074 || affix.indexOf(PATTERN_PER_MILLE) >= 0 3075 || affix.indexOf(PATTERN_DIGIT) >= 0 3076 || affix.indexOf(PATTERN_SEPARATOR) >= 0 3077 || affix.indexOf(PATTERN_MINUS) >= 0 3078 || affix.indexOf(CURRENCY_SIGN) >= 0; 3079 } 3080 if (needQuote) buffer.append('\''); 3081 if (affix.indexOf('\'') < 0) buffer.append(affix); 3082 else { 3083 for (int j=0; j<affix.length(); ++j) { 3084 char c = affix.charAt(j); 3085 buffer.append(c); 3086 if (c == '\'') buffer.append(c); 3087 } 3088 } 3089 if (needQuote) buffer.append('\''); 3090 } 3091 3092 /** 3093 * Does the real work of generating a pattern. */ 3094 private String toPattern(boolean localized) { 3095 StringBuffer result = new StringBuffer(); 3096 for (int j = 1; j >= 0; --j) { 3097 if (j == 1) 3098 appendAffix(result, posPrefixPattern, positivePrefix, localized); 3099 else appendAffix(result, negPrefixPattern, negativePrefix, localized); 3100 int i; 3101 int digitCount = useExponentialNotation 3102 ? getMaximumIntegerDigits() 3103 : Math.max(groupingSize, getMinimumIntegerDigits())+1; 3104 for (i = digitCount; i > 0; --i) { 3105 if (i != digitCount && isGroupingUsed() && groupingSize != 0 && 3106 i % groupingSize == 0) { 3107 result.append(localized ? symbols.getGroupingSeparator() : 3108 PATTERN_GROUPING_SEPARATOR); 3109 } 3110 result.append(i <= getMinimumIntegerDigits() 3111 ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT) 3112 : (localized ? symbols.getDigit() : PATTERN_DIGIT)); 3113 } 3114 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) 3115 result.append(localized ? symbols.getDecimalSeparator() : 3116 PATTERN_DECIMAL_SEPARATOR); 3117 for (i = 0; i < getMaximumFractionDigits(); ++i) { 3118 if (i < getMinimumFractionDigits()) { 3119 result.append(localized ? symbols.getZeroDigit() : 3120 PATTERN_ZERO_DIGIT); 3121 } else { 3122 result.append(localized ? symbols.getDigit() : 3123 PATTERN_DIGIT); 3124 } 3125 } 3126 if (useExponentialNotation) 3127 { 3128 result.append(localized ? symbols.getExponentSeparator() : 3129 PATTERN_EXPONENT); 3130 for (i=0; i<minExponentDigits; ++i) 3131 result.append(localized ? symbols.getZeroDigit() : 3132 PATTERN_ZERO_DIGIT); 3133 } 3134 if (j == 1) { 3135 appendAffix(result, posSuffixPattern, positiveSuffix, localized); 3136 if ((negSuffixPattern == posSuffixPattern && // n == p == null 3137 negativeSuffix.equals(positiveSuffix)) 3138 || (negSuffixPattern != null && 3139 negSuffixPattern.equals(posSuffixPattern))) { 3140 if ((negPrefixPattern != null && posPrefixPattern != null && 3141 negPrefixPattern.equals("'-" + posPrefixPattern)) || 3142 (negPrefixPattern == posPrefixPattern && // n == p == null 3143 negativePrefix.equals(symbols.getMinusSign() + positivePrefix))) 3144 break; 3145 } 3146 result.append(localized ? symbols.getPatternSeparator() : 3147 PATTERN_SEPARATOR); 3148 } else appendAffix(result, negSuffixPattern, negativeSuffix, localized); 3149 } 3150 return result.toString(); 3151 } 3152 3153 /** 3154 * Apply the given pattern to this Format object. A pattern is a 3155 * short-hand specification for the various formatting properties. 3156 * These properties can also be changed individually through the 3157 * various setter methods. 3158 * <p> 3159 * There is no limit to integer digits set 3160 * by this routine, since that is the typical end-user desire; 3161 * use setMaximumInteger if you want to set a real value. 3162 * For negative numbers, use a second pattern, separated by a semicolon 3163 * <P>Example <code>"#,#00.0#"</code> → 1,234.56 3164 * <P>This means a minimum of 2 integer digits, 1 fraction digit, and 3165 * a maximum of 2 fraction digits. 3166 * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in 3167 * parentheses. 3168 * <p>In negative patterns, the minimum and maximum counts are ignored; 3169 * these are presumed to be set in the positive pattern. 3170 * 3171 * @param pattern a new pattern 3172 * @exception NullPointerException if <code>pattern</code> is null 3173 * @exception IllegalArgumentException if the given pattern is invalid. 3174 */ 3175 public void applyPattern(String pattern) { 3176 applyPattern(pattern, false); 3177 } 3178 3179 /** 3180 * Apply the given pattern to this Format object. The pattern 3181 * is assumed to be in a localized notation. A pattern is a 3182 * short-hand specification for the various formatting properties. 3183 * These properties can also be changed individually through the 3184 * various setter methods. 3185 * <p> 3186 * There is no limit to integer digits set 3187 * by this routine, since that is the typical end-user desire; 3188 * use setMaximumInteger if you want to set a real value. 3189 * For negative numbers, use a second pattern, separated by a semicolon 3190 * <P>Example <code>"#,#00.0#"</code> → 1,234.56 3191 * <P>This means a minimum of 2 integer digits, 1 fraction digit, and 3192 * a maximum of 2 fraction digits. 3193 * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in 3194 * parentheses. 3195 * <p>In negative patterns, the minimum and maximum counts are ignored; 3196 * these are presumed to be set in the positive pattern. 3197 * 3198 * @param pattern a new pattern 3199 * @exception NullPointerException if <code>pattern</code> is null 3200 * @exception IllegalArgumentException if the given pattern is invalid. 3201 */ 3202 public void applyLocalizedPattern(String pattern) { 3203 applyPattern(pattern, true); 3204 } 3205 3206 /** 3207 * Does the real work of applying a pattern. 3208 */ 3209 private void applyPattern(String pattern, boolean localized) { 3210 char zeroDigit = PATTERN_ZERO_DIGIT; 3211 char groupingSeparator = PATTERN_GROUPING_SEPARATOR; 3212 char decimalSeparator = PATTERN_DECIMAL_SEPARATOR; 3213 char percent = PATTERN_PERCENT; 3214 char perMill = PATTERN_PER_MILLE; 3215 char digit = PATTERN_DIGIT; 3216 char separator = PATTERN_SEPARATOR; 3217 String exponent = PATTERN_EXPONENT; 3218 char minus = PATTERN_MINUS; 3219 if (localized) { 3220 zeroDigit = symbols.getZeroDigit(); 3221 groupingSeparator = symbols.getGroupingSeparator(); 3222 decimalSeparator = symbols.getDecimalSeparator(); 3223 percent = symbols.getPercent(); 3224 perMill = symbols.getPerMill(); 3225 digit = symbols.getDigit(); 3226 separator = symbols.getPatternSeparator(); 3227 exponent = symbols.getExponentSeparator(); 3228 minus = symbols.getMinusSign(); 3229 } 3230 boolean gotNegative = false; 3231 decimalSeparatorAlwaysShown = false; 3232 isCurrencyFormat = false; 3233 useExponentialNotation = false; 3234 3235 int start = 0; 3236 for (int j = 1; j >= 0 && start < pattern.length(); --j) { 3237 boolean inQuote = false; 3238 StringBuffer prefix = new StringBuffer(); 3239 StringBuffer suffix = new StringBuffer(); 3240 int decimalPos = -1; 3241 int multiplier = 1; 3242 int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0; 3243 byte groupingCount = -1; 3244 3245 // The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is 3246 // the section of the pattern with digits, decimal separator, 3247 // grouping characters. Phase 2 is the suffix. In phases 0 and 2, 3248 // percent, per mille, and currency symbols are recognized and 3249 // translated. The separation of the characters into phases is 3250 // strictly enforced; if phase 1 characters are to appear in the 3251 // suffix, for example, they must be quoted. 3252 int phase = 0; 3253 3254 // The affix is either the prefix or the suffix. 3255 StringBuffer affix = prefix; 3256 3257 for (int pos = start; pos < pattern.length(); ++pos) { 3258 char ch = pattern.charAt(pos); 3259 switch (phase) { 3260 case 0: 3261 case 2: 3262 // Process the prefix / suffix characters 3263 if (inQuote) { 3264 // A quote within quotes indicates either the closing 3265 // quote or two quotes, which is a quote literal. That 3266 // is, we have the second quote in 'do' or 'don''t'. 3267 if (ch == QUOTE) { 3268 if ((pos+1) < pattern.length() && 3269 pattern.charAt(pos+1) == QUOTE) { 3270 ++pos; 3271 affix.append("''"); // 'don''t' 3272 } else { 3273 inQuote = false; // 'do' 3274 } 3275 continue; 3276 } 3277 } else { 3278 // Process unquoted characters seen in prefix or suffix 3279 // phase. 3280 if (ch == digit || 3281 ch == zeroDigit || 3282 ch == groupingSeparator || 3283 ch == decimalSeparator) { 3284 phase = 1; 3285 --pos; // Reprocess this character 3286 continue; 3287 } else if (ch == CURRENCY_SIGN) { 3288 // Use lookahead to determine if the currency sign 3289 // is doubled or not. 3290 boolean doubled = (pos + 1) < pattern.length() && 3291 pattern.charAt(pos + 1) == CURRENCY_SIGN; 3292 if (doubled) { // Skip over the doubled character 3293 ++pos; 3294 } 3295 isCurrencyFormat = true; 3296 affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4"); 3297 continue; 3298 } else if (ch == QUOTE) { 3299 // A quote outside quotes indicates either the 3300 // opening quote or two quotes, which is a quote 3301 // literal. That is, we have the first quote in 'do' 3302 // or o''clock. 3303 if (ch == QUOTE) { 3304 if ((pos+1) < pattern.length() && 3305 pattern.charAt(pos+1) == QUOTE) { 3306 ++pos; 3307 affix.append("''"); // o''clock 3308 } else { 3309 inQuote = true; // 'do' 3310 } 3311 continue; 3312 } 3313 } else if (ch == separator) { 3314 // Don't allow separators before we see digit 3315 // characters of phase 1, and don't allow separators 3316 // in the second pattern (j == 0). 3317 if (phase == 0 || j == 0) { 3318 throw new IllegalArgumentException("Unquoted special character '" + 3319 ch + "' in pattern \"" + pattern + '"'); 3320 } 3321 start = pos + 1; 3322 pos = pattern.length(); 3323 continue; 3324 } 3325 3326 // Next handle characters which are appended directly. 3327 else if (ch == percent) { 3328 if (multiplier != 1) { 3329 throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" + 3330 pattern + '"'); 3331 } 3332 multiplier = 100; 3333 affix.append("'%"); 3334 continue; 3335 } else if (ch == perMill) { 3336 if (multiplier != 1) { 3337 throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" + 3338 pattern + '"'); 3339 } 3340 multiplier = 1000; 3341 affix.append("'\u2030"); 3342 continue; 3343 } else if (ch == minus) { 3344 affix.append("'-"); 3345 continue; 3346 } 3347 } 3348 // Note that if we are within quotes, or if this is an 3349 // unquoted, non-special character, then we usually fall 3350 // through to here. 3351 affix.append(ch); 3352 break; 3353 3354 case 1: 3355 // The negative subpattern (j = 0) serves only to specify the 3356 // negative prefix and suffix, so all the phase 1 characters 3357 // e.g. digits, zeroDigit, groupingSeparator, 3358 // decimalSeparator, exponent are ignored 3359 if (j == 0) { 3360 while (pos < pattern.length()) { 3361 char negPatternChar = pattern.charAt(pos); 3362 if (negPatternChar == digit 3363 || negPatternChar == zeroDigit 3364 || negPatternChar == groupingSeparator 3365 || negPatternChar == decimalSeparator) { 3366 ++pos; 3367 } else if (pattern.regionMatches(pos, exponent, 3368 0, exponent.length())) { 3369 pos = pos + exponent.length(); 3370 } else { 3371 // Not a phase 1 character, consider it as 3372 // suffix and parse it in phase 2 3373 --pos; //process it again in outer loop 3374 phase = 2; 3375 affix = suffix; 3376 break; 3377 } 3378 } 3379 continue; 3380 } 3381 3382 // Process the digits, decimal, and grouping characters. We 3383 // record five pieces of information. We expect the digits 3384 // to occur in the pattern ####0000.####, and we record the 3385 // number of left digits, zero (central) digits, and right 3386 // digits. The position of the last grouping character is 3387 // recorded (should be somewhere within the first two blocks 3388 // of characters), as is the position of the decimal point, 3389 // if any (should be in the zero digits). If there is no 3390 // decimal point, then there should be no right digits. 3391 if (ch == digit) { 3392 if (zeroDigitCount > 0) { 3393 ++digitRightCount; 3394 } else { 3395 ++digitLeftCount; 3396 } 3397 if (groupingCount >= 0 && decimalPos < 0) { 3398 ++groupingCount; 3399 } 3400 } else if (ch == zeroDigit) { 3401 if (digitRightCount > 0) { 3402 throw new IllegalArgumentException("Unexpected '0' in pattern \"" + 3403 pattern + '"'); 3404 } 3405 ++zeroDigitCount; 3406 if (groupingCount >= 0 && decimalPos < 0) { 3407 ++groupingCount; 3408 } 3409 } else if (ch == groupingSeparator) { 3410 groupingCount = 0; 3411 } else if (ch == decimalSeparator) { 3412 if (decimalPos >= 0) { 3413 throw new IllegalArgumentException("Multiple decimal separators in pattern \"" + 3414 pattern + '"'); 3415 } 3416 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; 3417 } else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){ 3418 if (useExponentialNotation) { 3419 throw new IllegalArgumentException("Multiple exponential " + 3420 "symbols in pattern \"" + pattern + '"'); 3421 } 3422 useExponentialNotation = true; 3423 minExponentDigits = 0; 3424 3425 // Use lookahead to parse out the exponential part 3426 // of the pattern, then jump into phase 2. 3427 pos = pos+exponent.length(); 3428 while (pos < pattern.length() && 3429 pattern.charAt(pos) == zeroDigit) { 3430 ++minExponentDigits; 3431 ++pos; 3432 } 3433 3434 if ((digitLeftCount + zeroDigitCount) < 1 || 3435 minExponentDigits < 1) { 3436 throw new IllegalArgumentException("Malformed exponential " + 3437 "pattern \"" + pattern + '"'); 3438 } 3439 3440 // Transition to phase 2 3441 phase = 2; 3442 affix = suffix; 3443 --pos; 3444 continue; 3445 } else { 3446 phase = 2; 3447 affix = suffix; 3448 --pos; 3449 continue; 3450 } 3451 break; 3452 } 3453 } 3454 3455 // Handle patterns with no '0' pattern character. These patterns 3456 // are legal, but must be interpreted. "##.###" -> "#0.###". 3457 // ".###" -> ".0##". 3458 /* We allow patterns of the form "####" to produce a zeroDigitCount 3459 * of zero (got that?); although this seems like it might make it 3460 * possible for format() to produce empty strings, format() checks 3461 * for this condition and outputs a zero digit in this situation. 3462 * Having a zeroDigitCount of zero yields a minimum integer digits 3463 * of zero, which allows proper round-trip patterns. That is, we 3464 * don't want "#" to become "#0" when toPattern() is called (even 3465 * though that's what it really is, semantically). 3466 */ 3467 if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) { 3468 // Handle "###.###" and "###." and ".###" 3469 int n = decimalPos; 3470 if (n == 0) { // Handle ".###" 3471 ++n; 3472 } 3473 digitRightCount = digitLeftCount - n; 3474 digitLeftCount = n - 1; 3475 zeroDigitCount = 1; 3476 } 3477 3478 // Do syntax checking on the digits. 3479 if ((decimalPos < 0 && digitRightCount > 0) || 3480 (decimalPos >= 0 && (decimalPos < digitLeftCount || 3481 decimalPos > (digitLeftCount + zeroDigitCount))) || 3482 groupingCount == 0 || inQuote) { 3483 throw new IllegalArgumentException("Malformed pattern \"" + 3484 pattern + '"'); 3485 } 3486 3487 if (j == 1) { 3488 posPrefixPattern = prefix.toString(); 3489 posSuffixPattern = suffix.toString(); 3490 negPrefixPattern = posPrefixPattern; // assume these for now 3491 negSuffixPattern = posSuffixPattern; 3492 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; 3493 /* The effectiveDecimalPos is the position the decimal is at or 3494 * would be at if there is no decimal. Note that if decimalPos<0, 3495 * then digitTotalCount == digitLeftCount + zeroDigitCount. 3496 */ 3497 int effectiveDecimalPos = decimalPos >= 0 ? 3498 decimalPos : digitTotalCount; 3499 setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount); 3500 setMaximumIntegerDigits(useExponentialNotation ? 3501 digitLeftCount + getMinimumIntegerDigits() : 3502 MAXIMUM_INTEGER_DIGITS); 3503 setMaximumFractionDigits(decimalPos >= 0 ? 3504 (digitTotalCount - decimalPos) : 0); 3505 setMinimumFractionDigits(decimalPos >= 0 ? 3506 (digitLeftCount + zeroDigitCount - decimalPos) : 0); 3507 setGroupingUsed(groupingCount > 0); 3508 this.groupingSize = (groupingCount > 0) ? groupingCount : 0; 3509 this.multiplier = multiplier; 3510 setDecimalSeparatorAlwaysShown(decimalPos == 0 || 3511 decimalPos == digitTotalCount); 3512 } else { 3513 negPrefixPattern = prefix.toString(); 3514 negSuffixPattern = suffix.toString(); 3515 gotNegative = true; 3516 } 3517 } 3518 3519 if (pattern.length() == 0) { 3520 posPrefixPattern = posSuffixPattern = ""; 3521 setMinimumIntegerDigits(0); 3522 setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS); 3523 setMinimumFractionDigits(0); 3524 setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS); 3525 } 3526 3527 // If there was no negative pattern, or if the negative pattern is 3528 // identical to the positive pattern, then prepend the minus sign to 3529 // the positive pattern to form the negative pattern. 3530 if (!gotNegative || 3531 (negPrefixPattern.equals(posPrefixPattern) 3532 && negSuffixPattern.equals(posSuffixPattern))) { 3533 negSuffixPattern = posSuffixPattern; 3534 negPrefixPattern = "'-" + posPrefixPattern; 3535 } 3536 3537 expandAffixes(); 3538 } 3539 3540 /** 3541 * Sets the maximum number of digits allowed in the integer portion of a 3542 * number. 3543 * For formatting numbers other than <code>BigInteger</code> and 3544 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and 3545 * 309 is used. Negative input values are replaced with 0. 3546 * @see NumberFormat#setMaximumIntegerDigits 3547 */ 3548 @Override 3549 public void setMaximumIntegerDigits(int newValue) { 3550 maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS); 3551 super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 3552 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits); 3553 if (minimumIntegerDigits > maximumIntegerDigits) { 3554 minimumIntegerDigits = maximumIntegerDigits; 3555 super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 3556 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits); 3557 } 3558 fastPathCheckNeeded = true; 3559 } 3560 3561 /** 3562 * Sets the minimum number of digits allowed in the integer portion of a 3563 * number. 3564 * For formatting numbers other than <code>BigInteger</code> and 3565 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and 3566 * 309 is used. Negative input values are replaced with 0. 3567 * @see NumberFormat#setMinimumIntegerDigits 3568 */ 3569 @Override 3570 public void setMinimumIntegerDigits(int newValue) { 3571 minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS); 3572 super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 3573 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits); 3574 if (minimumIntegerDigits > maximumIntegerDigits) { 3575 maximumIntegerDigits = minimumIntegerDigits; 3576 super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 3577 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits); 3578 } 3579 fastPathCheckNeeded = true; 3580 } 3581 3582 /** 3583 * Sets the maximum number of digits allowed in the fraction portion of a 3584 * number. 3585 * For formatting numbers other than <code>BigInteger</code> and 3586 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and 3587 * 340 is used. Negative input values are replaced with 0. 3588 * @see NumberFormat#setMaximumFractionDigits 3589 */ 3590 @Override 3591 public void setMaximumFractionDigits(int newValue) { 3592 maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS); 3593 super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 3594 DOUBLE_FRACTION_DIGITS : maximumFractionDigits); 3595 if (minimumFractionDigits > maximumFractionDigits) { 3596 minimumFractionDigits = maximumFractionDigits; 3597 super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 3598 DOUBLE_FRACTION_DIGITS : minimumFractionDigits); 3599 } 3600 fastPathCheckNeeded = true; 3601 } 3602 3603 /** 3604 * Sets the minimum number of digits allowed in the fraction portion of a 3605 * number. 3606 * For formatting numbers other than <code>BigInteger</code> and 3607 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and 3608 * 340 is used. Negative input values are replaced with 0. 3609 * @see NumberFormat#setMinimumFractionDigits 3610 */ 3611 @Override 3612 public void setMinimumFractionDigits(int newValue) { 3613 minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS); 3614 super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 3615 DOUBLE_FRACTION_DIGITS : minimumFractionDigits); 3616 if (minimumFractionDigits > maximumFractionDigits) { 3617 maximumFractionDigits = minimumFractionDigits; 3618 super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 3619 DOUBLE_FRACTION_DIGITS : maximumFractionDigits); 3620 } 3621 fastPathCheckNeeded = true; 3622 } 3623 3624 /** 3625 * Gets the maximum number of digits allowed in the integer portion of a 3626 * number. 3627 * For formatting numbers other than <code>BigInteger</code> and 3628 * <code>BigDecimal</code> objects, the lower of the return value and 3629 * 309 is used. 3630 * @see #setMaximumIntegerDigits 3631 */ 3632 @Override 3633 public int getMaximumIntegerDigits() { 3634 return maximumIntegerDigits; 3635 } 3636 3637 /** 3638 * Gets the minimum number of digits allowed in the integer portion of a 3639 * number. 3640 * For formatting numbers other than <code>BigInteger</code> and 3641 * <code>BigDecimal</code> objects, the lower of the return value and 3642 * 309 is used. 3643 * @see #setMinimumIntegerDigits 3644 */ 3645 @Override 3646 public int getMinimumIntegerDigits() { 3647 return minimumIntegerDigits; 3648 } 3649 3650 /** 3651 * Gets the maximum number of digits allowed in the fraction portion of a 3652 * number. 3653 * For formatting numbers other than <code>BigInteger</code> and 3654 * <code>BigDecimal</code> objects, the lower of the return value and 3655 * 340 is used. 3656 * @see #setMaximumFractionDigits 3657 */ 3658 @Override 3659 public int getMaximumFractionDigits() { 3660 return maximumFractionDigits; 3661 } 3662 3663 /** 3664 * Gets the minimum number of digits allowed in the fraction portion of a 3665 * number. 3666 * For formatting numbers other than <code>BigInteger</code> and 3667 * <code>BigDecimal</code> objects, the lower of the return value and 3668 * 340 is used. 3669 * @see #setMinimumFractionDigits 3670 */ 3671 @Override 3672 public int getMinimumFractionDigits() { 3673 return minimumFractionDigits; 3674 } 3675 3676 /** 3677 * Gets the currency used by this decimal format when formatting 3678 * currency values. 3679 * The currency is obtained by calling 3680 * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency} 3681 * on this number format's symbols. 3682 * 3683 * @return the currency used by this decimal format, or <code>null</code> 3684 * @since 1.4 3685 */ 3686 @Override 3687 public Currency getCurrency() { 3688 return symbols.getCurrency(); 3689 } 3690 3691 /** 3692 * Sets the currency used by this number format when formatting 3693 * currency values. This does not update the minimum or maximum 3694 * number of fraction digits used by the number format. 3695 * The currency is set by calling 3696 * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency} 3697 * on this number format's symbols. 3698 * 3699 * @param currency the new currency to be used by this decimal format 3700 * @exception NullPointerException if <code>currency</code> is null 3701 * @since 1.4 3702 */ 3703 @Override 3704 public void setCurrency(Currency currency) { 3705 if (currency != symbols.getCurrency()) { 3706 symbols.setCurrency(currency); 3707 if (isCurrencyFormat) { 3708 expandAffixes(); 3709 } 3710 } 3711 fastPathCheckNeeded = true; 3712 } 3713 3714 /** 3715 * Gets the {@link java.math.RoundingMode} used in this DecimalFormat. 3716 * 3717 * @return The <code>RoundingMode</code> used for this DecimalFormat. 3718 * @see #setRoundingMode(RoundingMode) 3719 * @since 1.6 3720 */ 3721 @Override 3722 public RoundingMode getRoundingMode() { 3723 return roundingMode; 3724 } 3725 3726 /** 3727 * Sets the {@link java.math.RoundingMode} used in this DecimalFormat. 3728 * 3729 * @param roundingMode The <code>RoundingMode</code> to be used 3730 * @see #getRoundingMode() 3731 * @exception NullPointerException if <code>roundingMode</code> is null. 3732 * @since 1.6 3733 */ 3734 @Override 3735 public void setRoundingMode(RoundingMode roundingMode) { 3736 if (roundingMode == null) { 3737 throw new NullPointerException(); 3738 } 3739 3740 this.roundingMode = roundingMode; 3741 digitList.setRoundingMode(roundingMode); 3742 fastPathCheckNeeded = true; 3743 } 3744 3745 /** 3746 * Reads the default serializable fields from the stream and performs 3747 * validations and adjustments for older serialized versions. The 3748 * validations and adjustments are: 3749 * <ol> 3750 * <li> 3751 * Verify that the superclass's digit count fields correctly reflect 3752 * the limits imposed on formatting numbers other than 3753 * <code>BigInteger</code> and <code>BigDecimal</code> objects. These 3754 * limits are stored in the superclass for serialization compatibility 3755 * with older versions, while the limits for <code>BigInteger</code> and 3756 * <code>BigDecimal</code> objects are kept in this class. 3757 * If, in the superclass, the minimum or maximum integer digit count is 3758 * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or 3759 * maximum fraction digit count is larger than 3760 * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid 3761 * and this method throws an <code>InvalidObjectException</code>. 3762 * <li> 3763 * If <code>serialVersionOnStream</code> is less than 4, initialize 3764 * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN 3765 * RoundingMode.HALF_EVEN}. This field is new with version 4. 3766 * <li> 3767 * If <code>serialVersionOnStream</code> is less than 3, then call 3768 * the setters for the minimum and maximum integer and fraction digits with 3769 * the values of the corresponding superclass getters to initialize the 3770 * fields in this class. The fields in this class are new with version 3. 3771 * <li> 3772 * If <code>serialVersionOnStream</code> is less than 1, indicating that 3773 * the stream was written by JDK 1.1, initialize 3774 * <code>useExponentialNotation</code> 3775 * to false, since it was not present in JDK 1.1. 3776 * <li> 3777 * Set <code>serialVersionOnStream</code> to the maximum allowed value so 3778 * that default serialization will work properly if this object is streamed 3779 * out again. 3780 * </ol> 3781 * 3782 * <p>Stream versions older than 2 will not have the affix pattern variables 3783 * <code>posPrefixPattern</code> etc. As a result, they will be initialized 3784 * to <code>null</code>, which means the affix strings will be taken as 3785 * literal values. This is exactly what we want, since that corresponds to 3786 * the pre-version-2 behavior. 3787 */ 3788 private void readObject(ObjectInputStream stream) 3789 throws IOException, ClassNotFoundException 3790 { 3791 stream.defaultReadObject(); 3792 digitList = new DigitList(); 3793 3794 // We force complete fast-path reinitialization when the instance is 3795 // deserialized. See clone() comment on fastPathCheckNeeded. 3796 fastPathCheckNeeded = true; 3797 isFastPath = false; 3798 fastPathData = null; 3799 3800 if (serialVersionOnStream < 4) { 3801 setRoundingMode(RoundingMode.HALF_EVEN); 3802 } else { 3803 setRoundingMode(getRoundingMode()); 3804 } 3805 3806 // We only need to check the maximum counts because NumberFormat 3807 // .readObject has already ensured that the maximum is greater than the 3808 // minimum count. 3809 if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS || 3810 super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { 3811 throw new InvalidObjectException("Digit count out of range"); 3812 } 3813 if (serialVersionOnStream < 3) { 3814 setMaximumIntegerDigits(super.getMaximumIntegerDigits()); 3815 setMinimumIntegerDigits(super.getMinimumIntegerDigits()); 3816 setMaximumFractionDigits(super.getMaximumFractionDigits()); 3817 setMinimumFractionDigits(super.getMinimumFractionDigits()); 3818 } 3819 if (serialVersionOnStream < 1) { 3820 // Didn't have exponential fields 3821 useExponentialNotation = false; 3822 } 3823 serialVersionOnStream = currentSerialVersion; 3824 } 3825 3826 //---------------------------------------------------------------------- 3827 // INSTANCE VARIABLES 3828 //---------------------------------------------------------------------- 3829 3830 private transient DigitList digitList = new DigitList(); 3831 3832 /** 3833 * The symbol used as a prefix when formatting positive numbers, e.g. "+". 3834 * 3835 * @serial 3836 * @see #getPositivePrefix 3837 */ 3838 private String positivePrefix = ""; 3839 3840 /** 3841 * The symbol used as a suffix when formatting positive numbers. 3842 * This is often an empty string. 3843 * 3844 * @serial 3845 * @see #getPositiveSuffix 3846 */ 3847 private String positiveSuffix = ""; 3848 3849 /** 3850 * The symbol used as a prefix when formatting negative numbers, e.g. "-". 3851 * 3852 * @serial 3853 * @see #getNegativePrefix 3854 */ 3855 private String negativePrefix = "-"; 3856 3857 /** 3858 * The symbol used as a suffix when formatting negative numbers. 3859 * This is often an empty string. 3860 * 3861 * @serial 3862 * @see #getNegativeSuffix 3863 */ 3864 private String negativeSuffix = ""; 3865 3866 /** 3867 * The prefix pattern for non-negative numbers. This variable corresponds 3868 * to <code>positivePrefix</code>. 3869 * 3870 * <p>This pattern is expanded by the method <code>expandAffix()</code> to 3871 * <code>positivePrefix</code> to update the latter to reflect changes in 3872 * <code>symbols</code>. If this variable is <code>null</code> then 3873 * <code>positivePrefix</code> is taken as a literal value that does not 3874 * change when <code>symbols</code> changes. This variable is always 3875 * <code>null</code> for <code>DecimalFormat</code> objects older than 3876 * stream version 2 restored from stream. 3877 * 3878 * @serial 3879 * @since 1.3 3880 */ 3881 private String posPrefixPattern; 3882 3883 /** 3884 * The suffix pattern for non-negative numbers. This variable corresponds 3885 * to <code>positiveSuffix</code>. This variable is analogous to 3886 * <code>posPrefixPattern</code>; see that variable for further 3887 * documentation. 3888 * 3889 * @serial 3890 * @since 1.3 3891 */ 3892 private String posSuffixPattern; 3893 3894 /** 3895 * The prefix pattern for negative numbers. This variable corresponds 3896 * to <code>negativePrefix</code>. This variable is analogous to 3897 * <code>posPrefixPattern</code>; see that variable for further 3898 * documentation. 3899 * 3900 * @serial 3901 * @since 1.3 3902 */ 3903 private String negPrefixPattern; 3904 3905 /** 3906 * The suffix pattern for negative numbers. This variable corresponds 3907 * to <code>negativeSuffix</code>. This variable is analogous to 3908 * <code>posPrefixPattern</code>; see that variable for further 3909 * documentation. 3910 * 3911 * @serial 3912 * @since 1.3 3913 */ 3914 private String negSuffixPattern; 3915 3916 /** 3917 * The multiplier for use in percent, per mille, etc. 3918 * 3919 * @serial 3920 * @see #getMultiplier 3921 */ 3922 private int multiplier = 1; 3923 3924 /** 3925 * The number of digits between grouping separators in the integer 3926 * portion of a number. Must be greater than 0 if 3927 * <code>NumberFormat.groupingUsed</code> is true. 3928 * 3929 * @serial 3930 * @see #getGroupingSize 3931 * @see java.text.NumberFormat#isGroupingUsed 3932 */ 3933 private byte groupingSize = 3; // invariant, > 0 if useThousands 3934 3935 /** 3936 * If true, forces the decimal separator to always appear in a formatted 3937 * number, even if the fractional part of the number is zero. 3938 * 3939 * @serial 3940 * @see #isDecimalSeparatorAlwaysShown 3941 */ 3942 private boolean decimalSeparatorAlwaysShown = false; 3943 3944 /** 3945 * If true, parse returns BigDecimal wherever possible. 3946 * 3947 * @serial 3948 * @see #isParseBigDecimal 3949 * @since 1.5 3950 */ 3951 private boolean parseBigDecimal = false; 3952 3953 3954 /** 3955 * True if this object represents a currency format. This determines 3956 * whether the monetary decimal separator is used instead of the normal one. 3957 */ 3958 private transient boolean isCurrencyFormat = false; 3959 3960 /** 3961 * The <code>DecimalFormatSymbols</code> object used by this format. 3962 * It contains the symbols used to format numbers, e.g. the grouping separator, 3963 * decimal separator, and so on. 3964 * 3965 * @serial 3966 * @see #setDecimalFormatSymbols 3967 * @see java.text.DecimalFormatSymbols 3968 */ 3969 private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols(); 3970 3971 /** 3972 * True to force the use of exponential (i.e. scientific) notation when formatting 3973 * numbers. 3974 * 3975 * @serial 3976 * @since 1.2 3977 */ 3978 private boolean useExponentialNotation; // Newly persistent in the Java 2 platform v.1.2 3979 3980 /** 3981 * FieldPositions describing the positive prefix String. This is 3982 * lazily created. Use <code>getPositivePrefixFieldPositions</code> 3983 * when needed. 3984 */ 3985 private transient FieldPosition[] positivePrefixFieldPositions; 3986 3987 /** 3988 * FieldPositions describing the positive suffix String. This is 3989 * lazily created. Use <code>getPositiveSuffixFieldPositions</code> 3990 * when needed. 3991 */ 3992 private transient FieldPosition[] positiveSuffixFieldPositions; 3993 3994 /** 3995 * FieldPositions describing the negative prefix String. This is 3996 * lazily created. Use <code>getNegativePrefixFieldPositions</code> 3997 * when needed. 3998 */ 3999 private transient FieldPosition[] negativePrefixFieldPositions; 4000 4001 /** 4002 * FieldPositions describing the negative suffix String. This is 4003 * lazily created. Use <code>getNegativeSuffixFieldPositions</code> 4004 * when needed. 4005 */ 4006 private transient FieldPosition[] negativeSuffixFieldPositions; 4007 4008 /** 4009 * The minimum number of digits used to display the exponent when a number is 4010 * formatted in exponential notation. This field is ignored if 4011 * <code>useExponentialNotation</code> is not true. 4012 * 4013 * @serial 4014 * @since 1.2 4015 */ 4016 private byte minExponentDigits; // Newly persistent in the Java 2 platform v.1.2 4017 4018 /** 4019 * The maximum number of digits allowed in the integer portion of a 4020 * <code>BigInteger</code> or <code>BigDecimal</code> number. 4021 * <code>maximumIntegerDigits</code> must be greater than or equal to 4022 * <code>minimumIntegerDigits</code>. 4023 * 4024 * @serial 4025 * @see #getMaximumIntegerDigits 4026 * @since 1.5 4027 */ 4028 private int maximumIntegerDigits = super.getMaximumIntegerDigits(); 4029 4030 /** 4031 * The minimum number of digits allowed in the integer portion of a 4032 * <code>BigInteger</code> or <code>BigDecimal</code> number. 4033 * <code>minimumIntegerDigits</code> must be less than or equal to 4034 * <code>maximumIntegerDigits</code>. 4035 * 4036 * @serial 4037 * @see #getMinimumIntegerDigits 4038 * @since 1.5 4039 */ 4040 private int minimumIntegerDigits = super.getMinimumIntegerDigits(); 4041 4042 /** 4043 * The maximum number of digits allowed in the fractional portion of a 4044 * <code>BigInteger</code> or <code>BigDecimal</code> number. 4045 * <code>maximumFractionDigits</code> must be greater than or equal to 4046 * <code>minimumFractionDigits</code>. 4047 * 4048 * @serial 4049 * @see #getMaximumFractionDigits 4050 * @since 1.5 4051 */ 4052 private int maximumFractionDigits = super.getMaximumFractionDigits(); 4053 4054 /** 4055 * The minimum number of digits allowed in the fractional portion of a 4056 * <code>BigInteger</code> or <code>BigDecimal</code> number. 4057 * <code>minimumFractionDigits</code> must be less than or equal to 4058 * <code>maximumFractionDigits</code>. 4059 * 4060 * @serial 4061 * @see #getMinimumFractionDigits 4062 * @since 1.5 4063 */ 4064 private int minimumFractionDigits = super.getMinimumFractionDigits(); 4065 4066 /** 4067 * The {@link java.math.RoundingMode} used in this DecimalFormat. 4068 * 4069 * @serial 4070 * @since 1.6 4071 */ 4072 private RoundingMode roundingMode = RoundingMode.HALF_EVEN; 4073 4074 // ------ DecimalFormat fields for fast-path for double algorithm ------ 4075 4076 /** 4077 * Helper inner utility class for storing the data used in the fast-path 4078 * algorithm. Almost all fields related to fast-path are encapsulated in 4079 * this class. 4080 * 4081 * Any {@code DecimalFormat} instance has a {@code fastPathData} 4082 * reference field that is null unless both the properties of the instance 4083 * are such that the instance is in the "fast-path" state, and a format call 4084 * has been done at least once while in this state. 4085 * 4086 * Almost all fields are related to the "fast-path" state only and don't 4087 * change until one of the instance properties is changed. 4088 * 4089 * {@code firstUsedIndex} and {@code lastFreeIndex} are the only 4090 * two fields that are used and modified while inside a call to 4091 * {@code fastDoubleFormat}. 4092 * 4093 */ 4094 private static class FastPathData { 4095 // --- Temporary fields used in fast-path, shared by several methods. 4096 4097 /** The first unused index at the end of the formatted result. */ 4098 int lastFreeIndex; 4099 4100 /** The first used index at the beginning of the formatted result */ 4101 int firstUsedIndex; 4102 4103 // --- State fields related to fast-path status. Changes due to a 4104 // property change only. Set by checkAndSetFastPathStatus() only. 4105 4106 /** Difference between locale zero and default zero representation. */ 4107 int zeroDelta; 4108 4109 /** Locale char for grouping separator. */ 4110 char groupingChar; 4111 4112 /** Fixed index position of last integral digit of formatted result */ 4113 int integralLastIndex; 4114 4115 /** Fixed index position of first fractional digit of formatted result */ 4116 int fractionalFirstIndex; 4117 4118 /** Fractional constants depending on decimal|currency state */ 4119 double fractionalScaleFactor; 4120 int fractionalMaxIntBound; 4121 4122 4123 /** The char array buffer that will contain the formatted result */ 4124 char[] fastPathContainer; 4125 4126 /** Suffixes recorded as char array for efficiency. */ 4127 char[] charsPositivePrefix; 4128 char[] charsNegativePrefix; 4129 char[] charsPositiveSuffix; 4130 char[] charsNegativeSuffix; 4131 boolean positiveAffixesRequired = true; 4132 boolean negativeAffixesRequired = true; 4133 } 4134 4135 /** The format fast-path status of the instance. Logical state. */ 4136 private transient boolean isFastPath = false; 4137 4138 /** Flag stating need of check and reinit fast-path status on next format call. */ 4139 private transient boolean fastPathCheckNeeded = true; 4140 4141 /** DecimalFormat reference to its FastPathData */ 4142 private transient FastPathData fastPathData; 4143 4144 4145 //---------------------------------------------------------------------- 4146 4147 static final int currentSerialVersion = 4; 4148 4149 /** 4150 * The internal serial version which says which version was written. 4151 * Possible values are: 4152 * <ul> 4153 * <li><b>0</b> (default): versions before the Java 2 platform v1.2 4154 * <li><b>1</b>: version for 1.2, which includes the two new fields 4155 * <code>useExponentialNotation</code> and 4156 * <code>minExponentDigits</code>. 4157 * <li><b>2</b>: version for 1.3 and later, which adds four new fields: 4158 * <code>posPrefixPattern</code>, <code>posSuffixPattern</code>, 4159 * <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>. 4160 * <li><b>3</b>: version for 1.5 and later, which adds five new fields: 4161 * <code>maximumIntegerDigits</code>, 4162 * <code>minimumIntegerDigits</code>, 4163 * <code>maximumFractionDigits</code>, 4164 * <code>minimumFractionDigits</code>, and 4165 * <code>parseBigDecimal</code>. 4166 * <li><b>4</b>: version for 1.6 and later, which adds one new field: 4167 * <code>roundingMode</code>. 4168 * </ul> 4169 * @since 1.2 4170 * @serial 4171 */ 4172 private int serialVersionOnStream = currentSerialVersion; 4173 4174 //---------------------------------------------------------------------- 4175 // CONSTANTS 4176 //---------------------------------------------------------------------- 4177 4178 // ------ Fast-Path for double Constants ------ 4179 4180 /** Maximum valid integer value for applying fast-path algorithm */ 4181 private static final double MAX_INT_AS_DOUBLE = (double) Integer.MAX_VALUE; 4182 4183 /** 4184 * The digit arrays used in the fast-path methods for collecting digits. 4185 * Using 3 constants arrays of chars ensures a very fast collection of digits 4186 */ 4187 private static class DigitArrays { 4188 static final char[] DigitOnes1000 = new char[1000]; 4189 static final char[] DigitTens1000 = new char[1000]; 4190 static final char[] DigitHundreds1000 = new char[1000]; 4191 4192 // initialize on demand holder class idiom for arrays of digits 4193 static { 4194 int tenIndex = 0; 4195 int hundredIndex = 0; 4196 char digitOne = '0'; 4197 char digitTen = '0'; 4198 char digitHundred = '0'; 4199 for (int i = 0; i < 1000; i++ ) { 4200 4201 DigitOnes1000[i] = digitOne; 4202 if (digitOne == '9') 4203 digitOne = '0'; 4204 else 4205 digitOne++; 4206 4207 DigitTens1000[i] = digitTen; 4208 if (i == (tenIndex + 9)) { 4209 tenIndex += 10; 4210 if (digitTen == '9') 4211 digitTen = '0'; 4212 else 4213 digitTen++; 4214 } 4215 4216 DigitHundreds1000[i] = digitHundred; 4217 if (i == (hundredIndex + 99)) { 4218 digitHundred++; 4219 hundredIndex += 100; 4220 } 4221 } 4222 } 4223 } 4224 // ------ Fast-Path for double Constants end ------ 4225 4226 // Constants for characters used in programmatic (unlocalized) patterns. 4227 private static final char PATTERN_ZERO_DIGIT = '0'; 4228 private static final char PATTERN_GROUPING_SEPARATOR = ','; 4229 private static final char PATTERN_DECIMAL_SEPARATOR = '.'; 4230 private static final char PATTERN_PER_MILLE = '\u2030'; 4231 private static final char PATTERN_PERCENT = '%'; 4232 private static final char PATTERN_DIGIT = '#'; 4233 private static final char PATTERN_SEPARATOR = ';'; 4234 private static final String PATTERN_EXPONENT = "E"; 4235 private static final char PATTERN_MINUS = '-'; 4236 4237 /** 4238 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It 4239 * is used in patterns and substituted with either the currency symbol, 4240 * or if it is doubled, with the international currency symbol. If the 4241 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is 4242 * replaced with the monetary decimal separator. 4243 * 4244 * The CURRENCY_SIGN is not localized. 4245 */ 4246 private static final char CURRENCY_SIGN = '\u00A4'; 4247 4248 private static final char QUOTE = '\''; 4249 4250 private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0]; 4251 4252 // Upper limit on integer and fraction digits for a Java double 4253 static final int DOUBLE_INTEGER_DIGITS = 309; 4254 static final int DOUBLE_FRACTION_DIGITS = 340; 4255 4256 // Upper limit on integer and fraction digits for BigDecimal and BigInteger 4257 static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE; 4258 static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE; 4259 4260 // Proclaim JDK 1.1 serial compatibility. 4261 static final long serialVersionUID = 864413376551465018L; 4262 }