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