Print this page
rev 5696 : 6336885: RFE: Locale Data Deployment Enhancements
4609153: Provide locale data for Indic locales
5104387: Support for gl_ES locale (galician language)
6337471: desktop/system locale preferences support
7056139: (cal) SPI support for locale-dependent Calendar parameters
7058206: Provide CalendarData SPI for week params and display field value names
7073852: Support multiple scripts for digits and decimal symbols per locale
7079560: [Fmt-Da] Context dependent month names support in SimpleDateFormat
7171324: getAvailableLocales() of locale sensitive services should return the actual availability of locales
7151414: (cal) Support calendar type identification
7168528: LocaleServiceProvider needs to be aware of Locale extensions
7171372: (cal) locale's default Calendar should be created if unknown calendar is specified
Summary: JEP 127: Improve Locale Data Packaging and Adopt Unicode CLDR Data (part 1 w/o packaging changes. by Naoto Sato and Masayoshi Okutsu)
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/java/text/DecimalFormat.java
+++ new/src/share/classes/java/text/DecimalFormat.java
1 1 /*
2 - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
2 + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26 /*
27 27 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28 28 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29 29 *
30 30 * The original version of this source code and documentation is copyrighted
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
31 31 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
32 32 * materials are provided under terms of a License Agreement between Taligent
33 33 * and Sun. This technology is protected by multiple US and International
34 34 * patents. This notice and attribution to Taligent may not be removed.
35 35 * Taligent is a registered trademark of Taligent, Inc.
36 36 *
37 37 */
38 38
39 39 package java.text;
40 40
41 -import java.io.InvalidObjectException;
42 41 import java.io.IOException;
42 +import java.io.InvalidObjectException;
43 43 import java.io.ObjectInputStream;
44 44 import java.math.BigDecimal;
45 45 import java.math.BigInteger;
46 46 import java.math.RoundingMode;
47 +import java.text.spi.NumberFormatProvider;
47 48 import java.util.ArrayList;
48 49 import java.util.Currency;
49 50 import java.util.Locale;
50 51 import java.util.ResourceBundle;
51 52 import java.util.concurrent.ConcurrentHashMap;
52 53 import java.util.concurrent.ConcurrentMap;
53 54 import java.util.concurrent.atomic.AtomicInteger;
54 55 import java.util.concurrent.atomic.AtomicLong;
55 -import sun.util.resources.LocaleData;
56 +import sun.util.locale.provider.LocaleProviderAdapter;
56 57
57 58 /**
58 59 * <code>DecimalFormat</code> is a concrete subclass of
59 60 * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
60 61 * features designed to make it possible to parse and format numbers in any
61 62 * locale, including support for Western, Arabic, and Indic digits. It also
62 63 * supports different kinds of numbers, including integers (123), fixed-point
63 64 * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
64 65 * currency amounts ($123). All of these can be localized.
65 66 *
66 67 * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
67 68 * default locale, call one of <code>NumberFormat</code>'s factory methods, such
68 69 * as <code>getInstance()</code>. In general, do not call the
69 70 * <code>DecimalFormat</code> constructors directly, since the
70 71 * <code>NumberFormat</code> factory methods may return subclasses other than
71 72 * <code>DecimalFormat</code>. If you need to customize the format object, do
72 73 * something like this:
73 74 *
74 75 * <blockquote><pre>
75 76 * NumberFormat f = NumberFormat.getInstance(loc);
76 77 * if (f instanceof DecimalFormat) {
77 78 * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
78 79 * }
79 80 * </pre></blockquote>
80 81 *
81 82 * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
82 83 * <em>symbols</em>. The pattern may be set directly using
83 84 * <code>applyPattern()</code>, or indirectly using the API methods. The
84 85 * symbols are stored in a <code>DecimalFormatSymbols</code> object. When using
85 86 * the <code>NumberFormat</code> factory methods, the pattern and symbols are
86 87 * read from localized <code>ResourceBundle</code>s.
87 88 *
88 89 * <h4>Patterns</h4>
89 90 *
90 91 * <code>DecimalFormat</code> patterns have the following syntax:
91 92 * <blockquote><pre>
92 93 * <i>Pattern:</i>
93 94 * <i>PositivePattern</i>
94 95 * <i>PositivePattern</i> ; <i>NegativePattern</i>
95 96 * <i>PositivePattern:</i>
96 97 * <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
97 98 * <i>NegativePattern:</i>
98 99 * <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
99 100 * <i>Prefix:</i>
100 101 * any Unicode characters except \uFFFE, \uFFFF, and special characters
101 102 * <i>Suffix:</i>
102 103 * any Unicode characters except \uFFFE, \uFFFF, and special characters
103 104 * <i>Number:</i>
104 105 * <i>Integer</i> <i>Exponent<sub>opt</sub></i>
105 106 * <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
106 107 * <i>Integer:</i>
107 108 * <i>MinimumInteger</i>
108 109 * #
109 110 * # <i>Integer</i>
110 111 * # , <i>Integer</i>
111 112 * <i>MinimumInteger:</i>
112 113 * 0
113 114 * 0 <i>MinimumInteger</i>
114 115 * 0 , <i>MinimumInteger</i>
115 116 * <i>Fraction:</i>
116 117 * <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
117 118 * <i>MinimumFraction:</i>
118 119 * 0 <i>MinimumFraction<sub>opt</sub></i>
119 120 * <i>OptionalFraction:</i>
120 121 * # <i>OptionalFraction<sub>opt</sub></i>
121 122 * <i>Exponent:</i>
122 123 * E <i>MinimumExponent</i>
123 124 * <i>MinimumExponent:</i>
124 125 * 0 <i>MinimumExponent<sub>opt</sub></i>
125 126 * </pre></blockquote>
126 127 *
127 128 * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
128 129 * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>. Each
129 130 * subpattern has a prefix, numeric part, and suffix. The negative subpattern
130 131 * is optional; if absent, then the positive subpattern prefixed with the
131 132 * localized minus sign (<code>'-'</code> in most locales) is used as the
132 133 * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
133 134 * <code>"0.00;-0.00"</code>. If there is an explicit negative subpattern, it
134 135 * serves only to specify the negative prefix and suffix; the number of digits,
135 136 * minimal digits, and other characteristics are all the same as the positive
136 137 * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
137 138 * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
138 139 *
139 140 * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
140 141 * thousands separators, decimal separators, etc. may be set to arbitrary
141 142 * values, and they will appear properly during formatting. However, care must
142 143 * be taken that the symbols and strings do not conflict, or parsing will be
143 144 * unreliable. For example, either the positive and negative prefixes or the
144 145 * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
145 146 * to distinguish positive from negative values. (If they are identical, then
146 147 * <code>DecimalFormat</code> will behave as if no negative subpattern was
147 148 * specified.) Another example is that the decimal separator and thousands
148 149 * separator should be distinct characters, or parsing will be impossible.
149 150 *
150 151 * <p>The grouping separator is commonly used for thousands, but in some
151 152 * countries it separates ten-thousands. The grouping size is a constant number
152 153 * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
153 154 * 1,0000,0000. If you supply a pattern with multiple grouping characters, the
154 155 * interval between the last one and the end of the integer is the one that is
155 156 * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
156 157 * <code>"##,####,####"</code>.
157 158 *
158 159 * <h4>Special Pattern Characters</h4>
159 160 *
160 161 * <p>Many characters in a pattern are taken literally; they are matched during
161 162 * parsing and output unchanged during formatting. Special characters, on the
162 163 * other hand, stand for other characters, strings, or classes of characters.
163 164 * They must be quoted, unless noted otherwise, if they are to appear in the
164 165 * prefix or suffix as literals.
165 166 *
166 167 * <p>The characters listed here are used in non-localized patterns. Localized
167 168 * patterns use the corresponding characters taken from this formatter's
168 169 * <code>DecimalFormatSymbols</code> object instead, and these characters lose
169 170 * their special status. Two exceptions are the currency sign and quote, which
170 171 * are not localized.
171 172 *
172 173 * <blockquote>
173 174 * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
174 175 * location, localized, and meaning.">
175 176 * <tr bgcolor="#ccccff">
176 177 * <th align=left>Symbol
177 178 * <th align=left>Location
178 179 * <th align=left>Localized?
179 180 * <th align=left>Meaning
180 181 * <tr valign=top>
181 182 * <td><code>0</code>
182 183 * <td>Number
183 184 * <td>Yes
184 185 * <td>Digit
185 186 * <tr valign=top bgcolor="#eeeeff">
186 187 * <td><code>#</code>
187 188 * <td>Number
188 189 * <td>Yes
189 190 * <td>Digit, zero shows as absent
190 191 * <tr valign=top>
191 192 * <td><code>.</code>
192 193 * <td>Number
193 194 * <td>Yes
194 195 * <td>Decimal separator or monetary decimal separator
195 196 * <tr valign=top bgcolor="#eeeeff">
196 197 * <td><code>-</code>
197 198 * <td>Number
198 199 * <td>Yes
199 200 * <td>Minus sign
200 201 * <tr valign=top>
201 202 * <td><code>,</code>
202 203 * <td>Number
203 204 * <td>Yes
204 205 * <td>Grouping separator
205 206 * <tr valign=top bgcolor="#eeeeff">
206 207 * <td><code>E</code>
207 208 * <td>Number
208 209 * <td>Yes
209 210 * <td>Separates mantissa and exponent in scientific notation.
210 211 * <em>Need not be quoted in prefix or suffix.</em>
211 212 * <tr valign=top>
212 213 * <td><code>;</code>
213 214 * <td>Subpattern boundary
214 215 * <td>Yes
215 216 * <td>Separates positive and negative subpatterns
216 217 * <tr valign=top bgcolor="#eeeeff">
217 218 * <td><code>%</code>
218 219 * <td>Prefix or suffix
219 220 * <td>Yes
220 221 * <td>Multiply by 100 and show as percentage
221 222 * <tr valign=top>
222 223 * <td><code>\u2030</code>
223 224 * <td>Prefix or suffix
224 225 * <td>Yes
225 226 * <td>Multiply by 1000 and show as per mille value
226 227 * <tr valign=top bgcolor="#eeeeff">
227 228 * <td><code>¤</code> (<code>\u00A4</code>)
228 229 * <td>Prefix or suffix
229 230 * <td>No
230 231 * <td>Currency sign, replaced by currency symbol. If
231 232 * doubled, replaced by international currency symbol.
232 233 * If present in a pattern, the monetary decimal separator
233 234 * is used instead of the decimal separator.
234 235 * <tr valign=top>
235 236 * <td><code>'</code>
236 237 * <td>Prefix or suffix
237 238 * <td>No
238 239 * <td>Used to quote special characters in a prefix or suffix,
239 240 * for example, <code>"'#'#"</code> formats 123 to
240 241 * <code>"#123"</code>. To create a single quote
241 242 * itself, use two in a row: <code>"# o''clock"</code>.
242 243 * </table>
243 244 * </blockquote>
244 245 *
245 246 * <h4>Scientific Notation</h4>
246 247 *
247 248 * <p>Numbers in scientific notation are expressed as the product of a mantissa
248 249 * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The
249 250 * mantissa is often in the range 1.0 <= x < 10.0, but it need not be.
250 251 * <code>DecimalFormat</code> can be instructed to format and parse scientific
251 252 * notation <em>only via a pattern</em>; there is currently no factory method
252 253 * that creates a scientific notation format. In a pattern, the exponent
253 254 * character immediately followed by one or more digit characters indicates
254 255 * scientific notation. Example: <code>"0.###E0"</code> formats the number
255 256 * 1234 as <code>"1.234E3"</code>.
256 257 *
257 258 * <ul>
258 259 * <li>The number of digit characters after the exponent character gives the
259 260 * minimum exponent digit count. There is no maximum. Negative exponents are
260 261 * formatted using the localized minus sign, <em>not</em> the prefix and suffix
261 262 * from the pattern. This allows patterns such as <code>"0.###E0 m/s"</code>.
262 263 *
263 264 * <li>The minimum and maximum number of integer digits are interpreted
264 265 * together:
265 266 *
266 267 * <ul>
267 268 * <li>If the maximum number of integer digits is greater than their minimum number
268 269 * and greater than 1, it forces the exponent to be a multiple of the maximum
269 270 * number of integer digits, and the minimum number of integer digits to be
270 271 * interpreted as 1. The most common use of this is to generate
271 272 * <em>engineering notation</em>, in which the exponent is a multiple of three,
272 273 * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
273 274 * formats to <code>"12.345E3"</code>, and 123456 formats to
274 275 * <code>"123.456E3"</code>.
275 276 *
276 277 * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
277 278 * exponent. Example: 0.00123 formatted with <code>"00.###E0"</code> yields
278 279 * <code>"12.3E-4"</code>.
279 280 * </ul>
280 281 *
281 282 * <li>The number of significant digits in the mantissa is the sum of the
282 283 * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
283 284 * unaffected by the maximum integer digits. For example, 12345 formatted with
284 285 * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
285 286 * the significant digits count to zero. The number of significant digits
286 287 * does not affect parsing.
287 288 *
288 289 * <li>Exponential patterns may not contain grouping separators.
289 290 * </ul>
290 291 *
291 292 * <h4>Rounding</h4>
292 293 *
293 294 * <code>DecimalFormat</code> provides rounding modes defined in
294 295 * {@link java.math.RoundingMode} for formatting. By default, it uses
295 296 * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
296 297 *
297 298 * <h4>Digits</h4>
298 299 *
299 300 * For formatting, <code>DecimalFormat</code> uses the ten consecutive
300 301 * characters starting with the localized zero digit defined in the
301 302 * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
302 303 * digits as well as all Unicode decimal digits, as defined by
303 304 * {@link Character#digit Character.digit}, are recognized.
304 305 *
305 306 * <h4>Special Values</h4>
306 307 *
307 308 * <p><code>NaN</code> is formatted as a string, which typically has a single character
308 309 * <code>\uFFFD</code>. This string is determined by the
309 310 * <code>DecimalFormatSymbols</code> object. This is the only value for which
310 311 * the prefixes and suffixes are not used.
311 312 *
312 313 * <p>Infinity is formatted as a string, which typically has a single character
313 314 * <code>\u221E</code>, with the positive or negative prefixes and suffixes
314 315 * applied. The infinity string is determined by the
315 316 * <code>DecimalFormatSymbols</code> object.
316 317 *
317 318 * <p>Negative zero (<code>"-0"</code>) parses to
318 319 * <ul>
319 320 * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
320 321 * true,
321 322 * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
322 323 * and <code>isParseIntegerOnly()</code> is true,
323 324 * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
324 325 * and <code>isParseIntegerOnly()</code> are false.
325 326 * </ul>
326 327 *
327 328 * <h4><a name="synchronization">Synchronization</a></h4>
328 329 *
329 330 * <p>
330 331 * Decimal formats are generally not synchronized.
331 332 * It is recommended to create separate format instances for each thread.
332 333 * If multiple threads access a format concurrently, it must be synchronized
333 334 * externally.
334 335 *
335 336 * <h4>Example</h4>
336 337 *
337 338 * <blockquote><pre>
338 339 * <strong>// Print out a number using the localized number, integer, currency,
339 340 * // and percent format for each locale</strong>
340 341 * Locale[] locales = NumberFormat.getAvailableLocales();
341 342 * double myNumber = -1234.56;
342 343 * NumberFormat form;
343 344 * for (int j=0; j<4; ++j) {
344 345 * System.out.println("FORMAT");
345 346 * for (int i = 0; i < locales.length; ++i) {
346 347 * if (locales[i].getCountry().length() == 0) {
347 348 * continue; // Skip language-only locales
348 349 * }
349 350 * System.out.print(locales[i].getDisplayName());
350 351 * switch (j) {
351 352 * case 0:
352 353 * form = NumberFormat.getInstance(locales[i]); break;
353 354 * case 1:
354 355 * form = NumberFormat.getIntegerInstance(locales[i]); break;
355 356 * case 2:
356 357 * form = NumberFormat.getCurrencyInstance(locales[i]); break;
357 358 * default:
358 359 * form = NumberFormat.getPercentInstance(locales[i]); break;
359 360 * }
360 361 * if (form instanceof DecimalFormat) {
361 362 * System.out.print(": " + ((DecimalFormat) form).toPattern());
362 363 * }
363 364 * System.out.print(" -> " + form.format(myNumber));
364 365 * try {
365 366 * System.out.println(" -> " + form.parse(form.format(myNumber)));
366 367 * } catch (ParseException e) {}
367 368 * }
368 369 * }
369 370 * </pre></blockquote>
370 371 *
371 372 * @see <a href="http://java.sun.com/docs/books/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
372 373 * @see NumberFormat
373 374 * @see DecimalFormatSymbols
374 375 * @see ParsePosition
375 376 * @author Mark Davis
376 377 * @author Alan Liu
377 378 */
378 379 public class DecimalFormat extends NumberFormat {
379 380
380 381 /**
381 382 * Creates a DecimalFormat using the default pattern and symbols
382 383 * for the default locale. This is a convenient way to obtain a
383 384 * DecimalFormat when internationalization is not the main concern.
384 385 * <p>
385 386 * To obtain standard formats for a given locale, use the factory methods
386 387 * on NumberFormat such as getNumberInstance. These factories will
387 388 * return the most appropriate sub-class of NumberFormat for a given
388 389 * locale.
389 390 *
390 391 * @see java.text.NumberFormat#getInstance
↓ open down ↓ |
325 lines elided |
↑ open up ↑ |
391 392 * @see java.text.NumberFormat#getNumberInstance
392 393 * @see java.text.NumberFormat#getCurrencyInstance
393 394 * @see java.text.NumberFormat#getPercentInstance
394 395 */
395 396 public DecimalFormat() {
396 397 Locale def = Locale.getDefault(Locale.Category.FORMAT);
397 398 // try to get the pattern from the cache
398 399 String pattern = cachedLocaleData.get(def);
399 400 if (pattern == null) { /* cache miss */
400 401 // Get the pattern for the default locale.
401 - ResourceBundle rb = LocaleData.getNumberFormatData(def);
402 + LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
403 + switch (adapter.getAdapterType()) {
404 + case HOST:
405 + case SPI:
406 + adapter = LocaleProviderAdapter.getResourceBundleBased();
407 + break;
408 + }
409 + ResourceBundle rb = adapter.getLocaleData().getNumberFormatData(def);
402 410 String[] all = rb.getStringArray("NumberPatterns");
403 411 pattern = all[0];
404 412 /* update cache */
405 413 cachedLocaleData.putIfAbsent(def, pattern);
406 414 }
407 415
408 416 // Always applyPattern after the symbols are set
409 - this.symbols = new DecimalFormatSymbols(def);
417 + this.symbols = DecimalFormatSymbols.getInstance(def);
410 418 applyPattern(pattern, false);
411 419 }
412 420
413 421
414 422 /**
415 423 * Creates a DecimalFormat using the given pattern and the symbols
416 424 * for the default locale. This is a convenient way to obtain a
417 425 * DecimalFormat when internationalization is not the main concern.
418 426 * <p>
419 427 * To obtain standard formats for a given locale, use the factory methods
420 428 * on NumberFormat such as getNumberInstance. These factories will
421 429 * return the most appropriate sub-class of NumberFormat for a given
422 430 * locale.
423 431 *
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
424 432 * @param pattern A non-localized pattern string.
425 433 * @exception NullPointerException if <code>pattern</code> is null
426 434 * @exception IllegalArgumentException if the given pattern is invalid.
427 435 * @see java.text.NumberFormat#getInstance
428 436 * @see java.text.NumberFormat#getNumberInstance
429 437 * @see java.text.NumberFormat#getCurrencyInstance
430 438 * @see java.text.NumberFormat#getPercentInstance
431 439 */
432 440 public DecimalFormat(String pattern) {
433 441 // Always applyPattern after the symbols are set
434 - this.symbols = new DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT));
442 + this.symbols = DecimalFormatSymbols.getInstance(Locale.getDefault(Locale.Category.FORMAT));
435 443 applyPattern(pattern, false);
436 444 }
437 445
438 446
439 447 /**
440 448 * Creates a DecimalFormat using the given pattern and symbols.
441 449 * Use this constructor when you need to completely customize the
442 450 * behavior of the format.
443 451 * <p>
444 452 * To obtain standard formats for a given
445 453 * locale, use the factory methods on NumberFormat such as
446 454 * getInstance or getCurrencyInstance. If you need only minor adjustments
447 455 * to a standard format, you can modify the format returned by
448 456 * a NumberFormat factory method.
449 457 *
450 458 * @param pattern a non-localized pattern string
451 459 * @param symbols the set of symbols to be used
452 460 * @exception NullPointerException if any of the given arguments is null
453 461 * @exception IllegalArgumentException if the given pattern is invalid
454 462 * @see java.text.NumberFormat#getInstance
455 463 * @see java.text.NumberFormat#getNumberInstance
456 464 * @see java.text.NumberFormat#getCurrencyInstance
457 465 * @see java.text.NumberFormat#getPercentInstance
458 466 * @see java.text.DecimalFormatSymbols
459 467 */
460 468 public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
461 469 // Always applyPattern after the symbols are set
462 470 this.symbols = (DecimalFormatSymbols)symbols.clone();
463 471 applyPattern(pattern, false);
464 472 }
465 473
466 474
467 475 // Overrides
468 476 /**
469 477 * Formats a number and appends the resulting text to the given string
470 478 * buffer.
471 479 * The number can be of any subclass of {@link java.lang.Number}.
472 480 * <p>
473 481 * This implementation uses the maximum precision permitted.
474 482 * @param number the number to format
475 483 * @param toAppendTo the <code>StringBuffer</code> to which the formatted
476 484 * text is to be appended
477 485 * @param pos On input: an alignment field, if desired.
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
478 486 * On output: the offsets of the alignment field.
479 487 * @return the value passed in as <code>toAppendTo</code>
480 488 * @exception IllegalArgumentException if <code>number</code> is
481 489 * null or not an instance of <code>Number</code>.
482 490 * @exception NullPointerException if <code>toAppendTo</code> or
483 491 * <code>pos</code> is null
484 492 * @exception ArithmeticException if rounding is needed with rounding
485 493 * mode being set to RoundingMode.UNNECESSARY
486 494 * @see java.text.FieldPosition
487 495 */
496 + @Override
488 497 public final StringBuffer format(Object number,
489 498 StringBuffer toAppendTo,
490 499 FieldPosition pos) {
491 500 if (number instanceof Long || number instanceof Integer ||
492 501 number instanceof Short || number instanceof Byte ||
493 502 number instanceof AtomicInteger ||
494 503 number instanceof AtomicLong ||
495 504 (number instanceof BigInteger &&
496 505 ((BigInteger)number).bitLength () < 64)) {
497 506 return format(((Number)number).longValue(), toAppendTo, pos);
498 507 } else if (number instanceof BigDecimal) {
499 508 return format((BigDecimal)number, toAppendTo, pos);
500 509 } else if (number instanceof BigInteger) {
501 510 return format((BigInteger)number, toAppendTo, pos);
502 511 } else if (number instanceof Number) {
503 512 return format(((Number)number).doubleValue(), toAppendTo, pos);
504 513 } else {
505 514 throw new IllegalArgumentException("Cannot format given Object as a Number");
506 515 }
507 516 }
508 517
509 518 /**
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
510 519 * Formats a double to produce a string.
511 520 * @param number The double to format
512 521 * @param result where the text is to be appended
513 522 * @param fieldPosition On input: an alignment field, if desired.
514 523 * On output: the offsets of the alignment field.
515 524 * @exception ArithmeticException if rounding is needed with rounding
516 525 * mode being set to RoundingMode.UNNECESSARY
517 526 * @return The formatted number string
518 527 * @see java.text.FieldPosition
519 528 */
529 + @Override
520 530 public StringBuffer format(double number, StringBuffer result,
521 531 FieldPosition fieldPosition) {
522 532 fieldPosition.setBeginIndex(0);
523 533 fieldPosition.setEndIndex(0);
524 534
525 535 return format(number, result, fieldPosition.getFieldDelegate());
526 536 }
527 537
528 538 /**
529 539 * Formats a double to produce a string.
530 540 * @param number The double to format
531 541 * @param result where the text is to be appended
532 542 * @param delegate notified of locations of sub fields
533 543 * @exception ArithmeticException if rounding is needed with rounding
534 544 * mode being set to RoundingMode.UNNECESSARY
535 545 * @return The formatted number string
536 546 */
537 547 private StringBuffer format(double number, StringBuffer result,
538 548 FieldDelegate delegate) {
539 549 if (Double.isNaN(number) ||
540 550 (Double.isInfinite(number) && multiplier == 0)) {
541 551 int iFieldStart = result.length();
542 552 result.append(symbols.getNaN());
543 553 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
544 554 iFieldStart, result.length(), result);
545 555 return result;
546 556 }
547 557
548 558 /* Detecting whether a double is negative is easy with the exception of
549 559 * the value -0.0. This is a double which has a zero mantissa (and
550 560 * exponent), but a negative sign bit. It is semantically distinct from
551 561 * a zero with a positive sign bit, and this distinction is important
552 562 * to certain kinds of computations. However, it's a little tricky to
553 563 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
554 564 * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
555 565 * -Infinity. Proper detection of -0.0 is needed to deal with the
556 566 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
557 567 */
558 568 boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0);
559 569
560 570 if (multiplier != 1) {
561 571 number *= multiplier;
562 572 }
563 573
564 574 if (Double.isInfinite(number)) {
565 575 if (isNegative) {
566 576 append(result, negativePrefix, delegate,
567 577 getNegativePrefixFieldPositions(), Field.SIGN);
568 578 } else {
569 579 append(result, positivePrefix, delegate,
570 580 getPositivePrefixFieldPositions(), Field.SIGN);
571 581 }
572 582
573 583 int iFieldStart = result.length();
574 584 result.append(symbols.getInfinity());
575 585 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
576 586 iFieldStart, result.length(), result);
577 587
578 588 if (isNegative) {
579 589 append(result, negativeSuffix, delegate,
580 590 getNegativeSuffixFieldPositions(), Field.SIGN);
581 591 } else {
582 592 append(result, positiveSuffix, delegate,
583 593 getPositiveSuffixFieldPositions(), Field.SIGN);
584 594 }
585 595
586 596 return result;
587 597 }
588 598
589 599 if (isNegative) {
590 600 number = -number;
591 601 }
592 602
593 603 // at this point we are guaranteed a nonnegative finite number.
594 604 assert(number >= 0 && !Double.isInfinite(number));
595 605
596 606 synchronized(digitList) {
597 607 int maxIntDigits = super.getMaximumIntegerDigits();
598 608 int minIntDigits = super.getMinimumIntegerDigits();
599 609 int maxFraDigits = super.getMaximumFractionDigits();
600 610 int minFraDigits = super.getMinimumFractionDigits();
601 611
602 612 digitList.set(isNegative, number, useExponentialNotation ?
603 613 maxIntDigits + maxFraDigits : maxFraDigits,
604 614 !useExponentialNotation);
605 615 return subformat(result, delegate, isNegative, false,
606 616 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
607 617 }
608 618 }
609 619
610 620 /**
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
611 621 * Format a long to produce a string.
612 622 * @param number The long to format
613 623 * @param result where the text is to be appended
614 624 * @param fieldPosition On input: an alignment field, if desired.
615 625 * On output: the offsets of the alignment field.
616 626 * @exception ArithmeticException if rounding is needed with rounding
617 627 * mode being set to RoundingMode.UNNECESSARY
618 628 * @return The formatted number string
619 629 * @see java.text.FieldPosition
620 630 */
631 + @Override
621 632 public StringBuffer format(long number, StringBuffer result,
622 633 FieldPosition fieldPosition) {
623 634 fieldPosition.setBeginIndex(0);
624 635 fieldPosition.setEndIndex(0);
625 636
626 637 return format(number, result, fieldPosition.getFieldDelegate());
627 638 }
628 639
629 640 /**
630 641 * Format a long to produce a string.
631 642 * @param number The long to format
632 643 * @param result where the text is to be appended
633 644 * @param delegate notified of locations of sub fields
634 645 * @return The formatted number string
635 646 * @exception ArithmeticException if rounding is needed with rounding
636 647 * mode being set to RoundingMode.UNNECESSARY
637 648 * @see java.text.FieldPosition
638 649 */
639 650 private StringBuffer format(long number, StringBuffer result,
640 651 FieldDelegate delegate) {
641 652 boolean isNegative = (number < 0);
642 653 if (isNegative) {
643 654 number = -number;
644 655 }
645 656
646 657 // In general, long values always represent real finite numbers, so
647 658 // we don't have to check for +/- Infinity or NaN. However, there
648 659 // is one case we have to be careful of: The multiplier can push
649 660 // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
650 661 // check for this before multiplying, and if it happens we use
651 662 // BigInteger instead.
652 663 boolean useBigInteger = false;
653 664 if (number < 0) { // This can only happen if number == Long.MIN_VALUE.
654 665 if (multiplier != 0) {
655 666 useBigInteger = true;
656 667 }
657 668 } else if (multiplier != 1 && multiplier != 0) {
658 669 long cutoff = Long.MAX_VALUE / multiplier;
659 670 if (cutoff < 0) {
660 671 cutoff = -cutoff;
661 672 }
662 673 useBigInteger = (number > cutoff);
663 674 }
664 675
665 676 if (useBigInteger) {
666 677 if (isNegative) {
667 678 number = -number;
668 679 }
669 680 BigInteger bigIntegerValue = BigInteger.valueOf(number);
670 681 return format(bigIntegerValue, result, delegate, true);
671 682 }
672 683
673 684 number *= multiplier;
674 685 if (number == 0) {
675 686 isNegative = false;
676 687 } else {
677 688 if (multiplier < 0) {
678 689 number = -number;
679 690 isNegative = !isNegative;
680 691 }
681 692 }
682 693
683 694 synchronized(digitList) {
684 695 int maxIntDigits = super.getMaximumIntegerDigits();
685 696 int minIntDigits = super.getMinimumIntegerDigits();
686 697 int maxFraDigits = super.getMaximumFractionDigits();
687 698 int minFraDigits = super.getMinimumFractionDigits();
688 699
689 700 digitList.set(isNegative, number,
690 701 useExponentialNotation ? maxIntDigits + maxFraDigits : 0);
691 702
692 703 return subformat(result, delegate, isNegative, true,
693 704 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
694 705 }
695 706 }
696 707
697 708 /**
698 709 * Formats a BigDecimal to produce a string.
699 710 * @param number The BigDecimal to format
700 711 * @param result where the text is to be appended
701 712 * @param fieldPosition On input: an alignment field, if desired.
702 713 * On output: the offsets of the alignment field.
703 714 * @return The formatted number string
704 715 * @exception ArithmeticException if rounding is needed with rounding
705 716 * mode being set to RoundingMode.UNNECESSARY
706 717 * @see java.text.FieldPosition
707 718 */
708 719 private StringBuffer format(BigDecimal number, StringBuffer result,
709 720 FieldPosition fieldPosition) {
710 721 fieldPosition.setBeginIndex(0);
711 722 fieldPosition.setEndIndex(0);
712 723 return format(number, result, fieldPosition.getFieldDelegate());
713 724 }
714 725
715 726 /**
716 727 * Formats a BigDecimal to produce a string.
717 728 * @param number The BigDecimal to format
718 729 * @param result where the text is to be appended
719 730 * @param delegate notified of locations of sub fields
720 731 * @exception ArithmeticException if rounding is needed with rounding
721 732 * mode being set to RoundingMode.UNNECESSARY
722 733 * @return The formatted number string
723 734 */
724 735 private StringBuffer format(BigDecimal number, StringBuffer result,
725 736 FieldDelegate delegate) {
726 737 if (multiplier != 1) {
727 738 number = number.multiply(getBigDecimalMultiplier());
728 739 }
729 740 boolean isNegative = number.signum() == -1;
730 741 if (isNegative) {
731 742 number = number.negate();
732 743 }
733 744
734 745 synchronized(digitList) {
735 746 int maxIntDigits = getMaximumIntegerDigits();
736 747 int minIntDigits = getMinimumIntegerDigits();
737 748 int maxFraDigits = getMaximumFractionDigits();
738 749 int minFraDigits = getMinimumFractionDigits();
739 750 int maximumDigits = maxIntDigits + maxFraDigits;
740 751
741 752 digitList.set(isNegative, number, useExponentialNotation ?
742 753 ((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) :
743 754 maxFraDigits, !useExponentialNotation);
744 755
745 756 return subformat(result, delegate, isNegative, false,
746 757 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
747 758 }
748 759 }
749 760
750 761 /**
751 762 * Format a BigInteger to produce a string.
752 763 * @param number The BigInteger to format
753 764 * @param result where the text is to be appended
754 765 * @param fieldPosition On input: an alignment field, if desired.
755 766 * On output: the offsets of the alignment field.
756 767 * @return The formatted number string
757 768 * @exception ArithmeticException if rounding is needed with rounding
758 769 * mode being set to RoundingMode.UNNECESSARY
759 770 * @see java.text.FieldPosition
760 771 */
761 772 private StringBuffer format(BigInteger number, StringBuffer result,
762 773 FieldPosition fieldPosition) {
763 774 fieldPosition.setBeginIndex(0);
764 775 fieldPosition.setEndIndex(0);
765 776
766 777 return format(number, result, fieldPosition.getFieldDelegate(), false);
767 778 }
768 779
769 780 /**
770 781 * Format a BigInteger to produce a string.
771 782 * @param number The BigInteger to format
772 783 * @param result where the text is to be appended
773 784 * @param delegate notified of locations of sub fields
774 785 * @return The formatted number string
775 786 * @exception ArithmeticException if rounding is needed with rounding
776 787 * mode being set to RoundingMode.UNNECESSARY
777 788 * @see java.text.FieldPosition
778 789 */
779 790 private StringBuffer format(BigInteger number, StringBuffer result,
780 791 FieldDelegate delegate, boolean formatLong) {
781 792 if (multiplier != 1) {
782 793 number = number.multiply(getBigIntegerMultiplier());
783 794 }
784 795 boolean isNegative = number.signum() == -1;
785 796 if (isNegative) {
786 797 number = number.negate();
787 798 }
788 799
789 800 synchronized(digitList) {
790 801 int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits;
791 802 if (formatLong) {
792 803 maxIntDigits = super.getMaximumIntegerDigits();
793 804 minIntDigits = super.getMinimumIntegerDigits();
794 805 maxFraDigits = super.getMaximumFractionDigits();
795 806 minFraDigits = super.getMinimumFractionDigits();
796 807 maximumDigits = maxIntDigits + maxFraDigits;
797 808 } else {
798 809 maxIntDigits = getMaximumIntegerDigits();
799 810 minIntDigits = getMinimumIntegerDigits();
800 811 maxFraDigits = getMaximumFractionDigits();
801 812 minFraDigits = getMinimumFractionDigits();
802 813 maximumDigits = maxIntDigits + maxFraDigits;
803 814 if (maximumDigits < 0) {
804 815 maximumDigits = Integer.MAX_VALUE;
805 816 }
806 817 }
807 818
808 819 digitList.set(isNegative, number,
809 820 useExponentialNotation ? maximumDigits : 0);
810 821
811 822 return subformat(result, delegate, isNegative, true,
812 823 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits);
813 824 }
814 825 }
815 826
816 827 /**
817 828 * Formats an Object producing an <code>AttributedCharacterIterator</code>.
818 829 * You can use the returned <code>AttributedCharacterIterator</code>
819 830 * to build the resulting String, as well as to determine information
820 831 * about the resulting String.
821 832 * <p>
822 833 * Each attribute key of the AttributedCharacterIterator will be of type
823 834 * <code>NumberFormat.Field</code>, with the attribute value being the
824 835 * same as the attribute key.
↓ open down ↓ |
194 lines elided |
↑ open up ↑ |
825 836 *
826 837 * @exception NullPointerException if obj is null.
827 838 * @exception IllegalArgumentException when the Format cannot format the
828 839 * given object.
829 840 * @exception ArithmeticException if rounding is needed with rounding
830 841 * mode being set to RoundingMode.UNNECESSARY
831 842 * @param obj The object to format
832 843 * @return AttributedCharacterIterator describing the formatted value.
833 844 * @since 1.4
834 845 */
846 + @Override
835 847 public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
836 848 CharacterIteratorFieldDelegate delegate =
837 849 new CharacterIteratorFieldDelegate();
838 850 StringBuffer sb = new StringBuffer();
839 851
840 852 if (obj instanceof Double || obj instanceof Float) {
841 853 format(((Number)obj).doubleValue(), sb, delegate);
842 854 } else if (obj instanceof Long || obj instanceof Integer ||
843 855 obj instanceof Short || obj instanceof Byte ||
844 856 obj instanceof AtomicInteger || obj instanceof AtomicLong) {
845 857 format(((Number)obj).longValue(), sb, delegate);
846 858 } else if (obj instanceof BigDecimal) {
847 859 format((BigDecimal)obj, sb, delegate);
848 860 } else if (obj instanceof BigInteger) {
849 861 format((BigInteger)obj, sb, delegate, false);
850 862 } else if (obj == null) {
851 863 throw new NullPointerException(
852 864 "formatToCharacterIterator must be passed non-null object");
853 865 } else {
854 866 throw new IllegalArgumentException(
855 867 "Cannot format given Object as a Number");
856 868 }
857 869 return delegate.getIterator(sb.toString());
858 870 }
859 871
860 872 /**
861 873 * Complete the formatting of a finite number. On entry, the digitList must
862 874 * be filled in with the correct digits.
863 875 */
864 876 private StringBuffer subformat(StringBuffer result, FieldDelegate delegate,
865 877 boolean isNegative, boolean isInteger,
866 878 int maxIntDigits, int minIntDigits,
867 879 int maxFraDigits, int minFraDigits) {
868 880 // NOTE: This isn't required anymore because DigitList takes care of this.
869 881 //
870 882 // // The negative of the exponent represents the number of leading
871 883 // // zeros between the decimal and the first non-zero digit, for
872 884 // // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this
873 885 // // is more than the maximum fraction digits, then we have an underflow
874 886 // // for the printed representation. We recognize this here and set
875 887 // // the DigitList representation to zero in this situation.
876 888 //
877 889 // if (-digitList.decimalAt >= getMaximumFractionDigits())
878 890 // {
879 891 // digitList.count = 0;
880 892 // }
881 893
882 894 char zero = symbols.getZeroDigit();
883 895 int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
884 896 char grouping = symbols.getGroupingSeparator();
885 897 char decimal = isCurrencyFormat ?
886 898 symbols.getMonetaryDecimalSeparator() :
887 899 symbols.getDecimalSeparator();
888 900
889 901 /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
890 902 * format as zero. This allows sensible computations and preserves
891 903 * relations such as signum(1/x) = signum(x), where x is +Infinity or
892 904 * -Infinity. Prior to this fix, we always formatted zero values as if
893 905 * they were positive. Liu 7/6/98.
894 906 */
895 907 if (digitList.isZero()) {
896 908 digitList.decimalAt = 0; // Normalize
897 909 }
898 910
899 911 if (isNegative) {
900 912 append(result, negativePrefix, delegate,
901 913 getNegativePrefixFieldPositions(), Field.SIGN);
902 914 } else {
903 915 append(result, positivePrefix, delegate,
904 916 getPositivePrefixFieldPositions(), Field.SIGN);
905 917 }
906 918
907 919 if (useExponentialNotation) {
908 920 int iFieldStart = result.length();
909 921 int iFieldEnd = -1;
910 922 int fFieldStart = -1;
911 923
912 924 // Minimum integer digits are handled in exponential format by
913 925 // adjusting the exponent. For example, 0.01234 with 3 minimum
914 926 // integer digits is "123.4E-4".
915 927
916 928 // Maximum integer digits are interpreted as indicating the
917 929 // repeating range. This is useful for engineering notation, in
918 930 // which the exponent is restricted to a multiple of 3. For
919 931 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
920 932 // If maximum integer digits are > 1 and are larger than
921 933 // minimum integer digits, then minimum integer digits are
922 934 // ignored.
923 935 int exponent = digitList.decimalAt;
924 936 int repeat = maxIntDigits;
925 937 int minimumIntegerDigits = minIntDigits;
926 938 if (repeat > 1 && repeat > minIntDigits) {
927 939 // A repeating range is defined; adjust to it as follows.
928 940 // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
929 941 // -3,-4,-5=>-6, etc. This takes into account that the
930 942 // exponent we have here is off by one from what we expect;
931 943 // it is for the format 0.MMMMMx10^n.
932 944 if (exponent >= 1) {
933 945 exponent = ((exponent - 1) / repeat) * repeat;
934 946 } else {
935 947 // integer division rounds towards 0
936 948 exponent = ((exponent - repeat) / repeat) * repeat;
937 949 }
938 950 minimumIntegerDigits = 1;
939 951 } else {
940 952 // No repeating range is defined; use minimum integer digits.
941 953 exponent -= minimumIntegerDigits;
942 954 }
943 955
944 956 // We now output a minimum number of digits, and more if there
945 957 // are more digits, up to the maximum number of digits. We
946 958 // place the decimal point after the "integer" digits, which
947 959 // are the first (decimalAt - exponent) digits.
948 960 int minimumDigits = minIntDigits + minFraDigits;
949 961 if (minimumDigits < 0) { // overflow?
950 962 minimumDigits = Integer.MAX_VALUE;
951 963 }
952 964
953 965 // The number of integer digits is handled specially if the number
954 966 // is zero, since then there may be no digits.
955 967 int integerDigits = digitList.isZero() ? minimumIntegerDigits :
956 968 digitList.decimalAt - exponent;
957 969 if (minimumDigits < integerDigits) {
958 970 minimumDigits = integerDigits;
959 971 }
960 972 int totalDigits = digitList.count;
961 973 if (minimumDigits > totalDigits) {
962 974 totalDigits = minimumDigits;
963 975 }
964 976 boolean addedDecimalSeparator = false;
965 977
966 978 for (int i=0; i<totalDigits; ++i) {
967 979 if (i == integerDigits) {
968 980 // Record field information for caller.
969 981 iFieldEnd = result.length();
970 982
971 983 result.append(decimal);
972 984 addedDecimalSeparator = true;
973 985
974 986 // Record field information for caller.
975 987 fFieldStart = result.length();
976 988 }
977 989 result.append((i < digitList.count) ?
978 990 (char)(digitList.digits[i] + zeroDelta) :
979 991 zero);
980 992 }
981 993
982 994 if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {
983 995 // Record field information for caller.
984 996 iFieldEnd = result.length();
985 997
986 998 result.append(decimal);
987 999 addedDecimalSeparator = true;
988 1000
989 1001 // Record field information for caller.
990 1002 fFieldStart = result.length();
991 1003 }
992 1004
993 1005 // Record field information
994 1006 if (iFieldEnd == -1) {
995 1007 iFieldEnd = result.length();
996 1008 }
997 1009 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
998 1010 iFieldStart, iFieldEnd, result);
999 1011 if (addedDecimalSeparator) {
1000 1012 delegate.formatted(Field.DECIMAL_SEPARATOR,
1001 1013 Field.DECIMAL_SEPARATOR,
1002 1014 iFieldEnd, fFieldStart, result);
1003 1015 }
1004 1016 if (fFieldStart == -1) {
1005 1017 fFieldStart = result.length();
1006 1018 }
1007 1019 delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
1008 1020 fFieldStart, result.length(), result);
1009 1021
1010 1022 // The exponent is output using the pattern-specified minimum
1011 1023 // exponent digits. There is no maximum limit to the exponent
1012 1024 // digits, since truncating the exponent would result in an
1013 1025 // unacceptable inaccuracy.
1014 1026 int fieldStart = result.length();
1015 1027
1016 1028 result.append(symbols.getExponentSeparator());
1017 1029
1018 1030 delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,
1019 1031 fieldStart, result.length(), result);
1020 1032
1021 1033 // For zero values, we force the exponent to zero. We
1022 1034 // must do this here, and not earlier, because the value
1023 1035 // is used to determine integer digit count above.
1024 1036 if (digitList.isZero()) {
1025 1037 exponent = 0;
1026 1038 }
1027 1039
1028 1040 boolean negativeExponent = exponent < 0;
1029 1041 if (negativeExponent) {
1030 1042 exponent = -exponent;
1031 1043 fieldStart = result.length();
1032 1044 result.append(symbols.getMinusSign());
1033 1045 delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
1034 1046 fieldStart, result.length(), result);
1035 1047 }
1036 1048 digitList.set(negativeExponent, exponent);
1037 1049
1038 1050 int eFieldStart = result.length();
1039 1051
1040 1052 for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {
1041 1053 result.append(zero);
1042 1054 }
1043 1055 for (int i=0; i<digitList.decimalAt; ++i) {
1044 1056 result.append((i < digitList.count) ?
1045 1057 (char)(digitList.digits[i] + zeroDelta) : zero);
1046 1058 }
1047 1059 delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,
1048 1060 result.length(), result);
1049 1061 } else {
1050 1062 int iFieldStart = result.length();
1051 1063
1052 1064 // Output the integer portion. Here 'count' is the total
1053 1065 // number of integer digits we will display, including both
1054 1066 // leading zeros required to satisfy getMinimumIntegerDigits,
1055 1067 // and actual digits present in the number.
1056 1068 int count = minIntDigits;
1057 1069 int digitIndex = 0; // Index into digitList.fDigits[]
1058 1070 if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
1059 1071 count = digitList.decimalAt;
1060 1072 }
1061 1073
1062 1074 // Handle the case where getMaximumIntegerDigits() is smaller
1063 1075 // than the real number of integer digits. If this is so, we
1064 1076 // output the least significant max integer digits. For example,
1065 1077 // the value 1997 printed with 2 max integer digits is just "97".
1066 1078 if (count > maxIntDigits) {
1067 1079 count = maxIntDigits;
1068 1080 digitIndex = digitList.decimalAt - count;
1069 1081 }
1070 1082
1071 1083 int sizeBeforeIntegerPart = result.length();
1072 1084 for (int i=count-1; i>=0; --i) {
1073 1085 if (i < digitList.decimalAt && digitIndex < digitList.count) {
1074 1086 // Output a real digit
1075 1087 result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
1076 1088 } else {
1077 1089 // Output a leading zero
1078 1090 result.append(zero);
1079 1091 }
1080 1092
1081 1093 // Output grouping separator if necessary. Don't output a
1082 1094 // grouping separator if i==0 though; that's at the end of
1083 1095 // the integer part.
1084 1096 if (isGroupingUsed() && i>0 && (groupingSize != 0) &&
1085 1097 (i % groupingSize == 0)) {
1086 1098 int gStart = result.length();
1087 1099 result.append(grouping);
1088 1100 delegate.formatted(Field.GROUPING_SEPARATOR,
1089 1101 Field.GROUPING_SEPARATOR, gStart,
1090 1102 result.length(), result);
1091 1103 }
1092 1104 }
1093 1105
1094 1106 // Determine whether or not there are any printable fractional
1095 1107 // digits. If we've used up the digits we know there aren't.
1096 1108 boolean fractionPresent = (minFraDigits > 0) ||
1097 1109 (!isInteger && digitIndex < digitList.count);
1098 1110
1099 1111 // If there is no fraction present, and we haven't printed any
1100 1112 // integer digits, then print a zero. Otherwise we won't print
1101 1113 // _any_ digits, and we won't be able to parse this string.
1102 1114 if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
1103 1115 result.append(zero);
1104 1116 }
1105 1117
1106 1118 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
1107 1119 iFieldStart, result.length(), result);
1108 1120
1109 1121 // Output the decimal separator if we always do so.
1110 1122 int sStart = result.length();
1111 1123 if (decimalSeparatorAlwaysShown || fractionPresent) {
1112 1124 result.append(decimal);
1113 1125 }
1114 1126
1115 1127 if (sStart != result.length()) {
1116 1128 delegate.formatted(Field.DECIMAL_SEPARATOR,
1117 1129 Field.DECIMAL_SEPARATOR,
1118 1130 sStart, result.length(), result);
1119 1131 }
1120 1132 int fFieldStart = result.length();
1121 1133
1122 1134 for (int i=0; i < maxFraDigits; ++i) {
1123 1135 // Here is where we escape from the loop. We escape if we've
1124 1136 // output the maximum fraction digits (specified in the for
1125 1137 // expression above).
1126 1138 // We also stop when we've output the minimum digits and either:
1127 1139 // we have an integer, so there is no fractional stuff to
1128 1140 // display, or we're out of significant digits.
1129 1141 if (i >= minFraDigits &&
1130 1142 (isInteger || digitIndex >= digitList.count)) {
1131 1143 break;
1132 1144 }
1133 1145
1134 1146 // Output leading fractional zeros. These are zeros that come
1135 1147 // after the decimal but before any significant digits. These
1136 1148 // are only output if abs(number being formatted) < 1.0.
1137 1149 if (-1-i > (digitList.decimalAt-1)) {
1138 1150 result.append(zero);
1139 1151 continue;
1140 1152 }
1141 1153
1142 1154 // Output a digit, if we have any precision left, or a
1143 1155 // zero if we don't. We don't want to output noise digits.
1144 1156 if (!isInteger && digitIndex < digitList.count) {
1145 1157 result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
1146 1158 } else {
1147 1159 result.append(zero);
1148 1160 }
1149 1161 }
1150 1162
1151 1163 // Record field information for caller.
1152 1164 delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
1153 1165 fFieldStart, result.length(), result);
1154 1166 }
1155 1167
1156 1168 if (isNegative) {
1157 1169 append(result, negativeSuffix, delegate,
1158 1170 getNegativeSuffixFieldPositions(), Field.SIGN);
1159 1171 }
1160 1172 else {
1161 1173 append(result, positiveSuffix, delegate,
1162 1174 getPositiveSuffixFieldPositions(), Field.SIGN);
1163 1175 }
1164 1176
1165 1177 return result;
1166 1178 }
1167 1179
1168 1180 /**
1169 1181 * Appends the String <code>string</code> to <code>result</code>.
1170 1182 * <code>delegate</code> is notified of all the
1171 1183 * <code>FieldPosition</code>s in <code>positions</code>.
1172 1184 * <p>
1173 1185 * If one of the <code>FieldPosition</code>s in <code>positions</code>
1174 1186 * identifies a <code>SIGN</code> attribute, it is mapped to
1175 1187 * <code>signAttribute</code>. This is used
1176 1188 * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
1177 1189 * attribute as necessary.
1178 1190 * <p>
1179 1191 * This is used by <code>subformat</code> to add the prefix/suffix.
1180 1192 */
1181 1193 private void append(StringBuffer result, String string,
1182 1194 FieldDelegate delegate,
1183 1195 FieldPosition[] positions,
1184 1196 Format.Field signAttribute) {
1185 1197 int start = result.length();
1186 1198
1187 1199 if (string.length() > 0) {
1188 1200 result.append(string);
1189 1201 for (int counter = 0, max = positions.length; counter < max;
1190 1202 counter++) {
1191 1203 FieldPosition fp = positions[counter];
1192 1204 Format.Field attribute = fp.getFieldAttribute();
1193 1205
1194 1206 if (attribute == Field.SIGN) {
1195 1207 attribute = signAttribute;
1196 1208 }
1197 1209 delegate.formatted(attribute, attribute,
1198 1210 start + fp.getBeginIndex(),
1199 1211 start + fp.getEndIndex(), result);
1200 1212 }
1201 1213 }
1202 1214 }
1203 1215
1204 1216 /**
1205 1217 * Parses text from a string to produce a <code>Number</code>.
1206 1218 * <p>
1207 1219 * The method attempts to parse text starting at the index given by
1208 1220 * <code>pos</code>.
1209 1221 * If parsing succeeds, then the index of <code>pos</code> is updated
1210 1222 * to the index after the last character used (parsing does not necessarily
1211 1223 * use all characters up to the end of the string), and the parsed
1212 1224 * number is returned. The updated <code>pos</code> can be used to
1213 1225 * indicate the starting point for the next call to this method.
1214 1226 * If an error occurs, then the index of <code>pos</code> is not
1215 1227 * changed, the error index of <code>pos</code> is set to the index of
1216 1228 * the character where the error occurred, and null is returned.
1217 1229 * <p>
1218 1230 * The subclass returned depends on the value of {@link #isParseBigDecimal}
1219 1231 * as well as on the string being parsed.
1220 1232 * <ul>
1221 1233 * <li>If <code>isParseBigDecimal()</code> is false (the default),
1222 1234 * most integer values are returned as <code>Long</code>
1223 1235 * objects, no matter how they are written: <code>"17"</code> and
1224 1236 * <code>"17.000"</code> both parse to <code>Long(17)</code>.
1225 1237 * Values that cannot fit into a <code>Long</code> are returned as
1226 1238 * <code>Double</code>s. This includes values with a fractional part,
1227 1239 * infinite values, <code>NaN</code>, and the value -0.0.
1228 1240 * <code>DecimalFormat</code> does <em>not</em> decide whether to
1229 1241 * return a <code>Double</code> or a <code>Long</code> based on the
1230 1242 * presence of a decimal separator in the source string. Doing so
1231 1243 * would prevent integers that overflow the mantissa of a double,
1232 1244 * such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
1233 1245 * parsed accurately.
1234 1246 * <p>
1235 1247 * Callers may use the <code>Number</code> methods
1236 1248 * <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
1237 1249 * the type they want.
1238 1250 * <li>If <code>isParseBigDecimal()</code> is true, values are returned
1239 1251 * as <code>BigDecimal</code> objects. The values are the ones
1240 1252 * constructed by {@link java.math.BigDecimal#BigDecimal(String)}
1241 1253 * for corresponding strings in locale-independent format. The
1242 1254 * special cases negative and positive infinity and NaN are returned
1243 1255 * as <code>Double</code> instances holding the values of the
1244 1256 * corresponding <code>Double</code> constants.
1245 1257 * </ul>
1246 1258 * <p>
1247 1259 * <code>DecimalFormat</code> parses all Unicode characters that represent
1248 1260 * decimal digits, as defined by <code>Character.digit()</code>. In
1249 1261 * addition, <code>DecimalFormat</code> also recognizes as digits the ten
↓ open down ↓ |
405 lines elided |
↑ open up ↑ |
1250 1262 * consecutive characters starting with the localized zero digit defined in
1251 1263 * the <code>DecimalFormatSymbols</code> object.
1252 1264 *
1253 1265 * @param text the string to be parsed
1254 1266 * @param pos A <code>ParsePosition</code> object with index and error
1255 1267 * index information as described above.
1256 1268 * @return the parsed value, or <code>null</code> if the parse fails
1257 1269 * @exception NullPointerException if <code>text</code> or
1258 1270 * <code>pos</code> is null.
1259 1271 */
1272 + @Override
1260 1273 public Number parse(String text, ParsePosition pos) {
1261 1274 // special case NaN
1262 1275 if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
1263 1276 pos.index = pos.index + symbols.getNaN().length();
1264 1277 return new Double(Double.NaN);
1265 1278 }
1266 1279
1267 1280 boolean[] status = new boolean[STATUS_LENGTH];
1268 1281 if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) {
1269 1282 return null;
1270 1283 }
1271 1284
1272 1285 // special case INFINITY
1273 1286 if (status[STATUS_INFINITE]) {
1274 1287 if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
1275 1288 return new Double(Double.POSITIVE_INFINITY);
1276 1289 } else {
1277 1290 return new Double(Double.NEGATIVE_INFINITY);
1278 1291 }
1279 1292 }
1280 1293
1281 1294 if (multiplier == 0) {
1282 1295 if (digitList.isZero()) {
1283 1296 return new Double(Double.NaN);
1284 1297 } else if (status[STATUS_POSITIVE]) {
1285 1298 return new Double(Double.POSITIVE_INFINITY);
1286 1299 } else {
1287 1300 return new Double(Double.NEGATIVE_INFINITY);
1288 1301 }
1289 1302 }
1290 1303
1291 1304 if (isParseBigDecimal()) {
1292 1305 BigDecimal bigDecimalResult = digitList.getBigDecimal();
1293 1306
1294 1307 if (multiplier != 1) {
1295 1308 try {
1296 1309 bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier());
1297 1310 }
1298 1311 catch (ArithmeticException e) { // non-terminating decimal expansion
1299 1312 bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), roundingMode);
1300 1313 }
1301 1314 }
1302 1315
1303 1316 if (!status[STATUS_POSITIVE]) {
1304 1317 bigDecimalResult = bigDecimalResult.negate();
1305 1318 }
1306 1319 return bigDecimalResult;
1307 1320 } else {
1308 1321 boolean gotDouble = true;
1309 1322 boolean gotLongMinimum = false;
1310 1323 double doubleResult = 0.0;
1311 1324 long longResult = 0;
1312 1325
1313 1326 // Finally, have DigitList parse the digits into a value.
1314 1327 if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) {
1315 1328 gotDouble = false;
1316 1329 longResult = digitList.getLong();
1317 1330 if (longResult < 0) { // got Long.MIN_VALUE
1318 1331 gotLongMinimum = true;
1319 1332 }
1320 1333 } else {
1321 1334 doubleResult = digitList.getDouble();
1322 1335 }
1323 1336
1324 1337 // Divide by multiplier. We have to be careful here not to do
1325 1338 // unneeded conversions between double and long.
1326 1339 if (multiplier != 1) {
1327 1340 if (gotDouble) {
1328 1341 doubleResult /= multiplier;
1329 1342 } else {
1330 1343 // Avoid converting to double if we can
1331 1344 if (longResult % multiplier == 0) {
1332 1345 longResult /= multiplier;
1333 1346 } else {
1334 1347 doubleResult = ((double)longResult) / multiplier;
1335 1348 gotDouble = true;
1336 1349 }
1337 1350 }
1338 1351 }
1339 1352
1340 1353 if (!status[STATUS_POSITIVE] && !gotLongMinimum) {
1341 1354 doubleResult = -doubleResult;
1342 1355 longResult = -longResult;
1343 1356 }
1344 1357
1345 1358 // At this point, if we divided the result by the multiplier, the
1346 1359 // result may fit into a long. We check for this case and return
1347 1360 // a long if possible.
1348 1361 // We must do this AFTER applying the negative (if appropriate)
1349 1362 // in order to handle the case of LONG_MIN; otherwise, if we do
1350 1363 // this with a positive value -LONG_MIN, the double is > 0, but
1351 1364 // the long is < 0. We also must retain a double in the case of
1352 1365 // -0.0, which will compare as == to a long 0 cast to a double
1353 1366 // (bug 4162852).
1354 1367 if (multiplier != 1 && gotDouble) {
1355 1368 longResult = (long)doubleResult;
1356 1369 gotDouble = ((doubleResult != (double)longResult) ||
1357 1370 (doubleResult == 0.0 && 1/doubleResult < 0.0)) &&
1358 1371 !isParseIntegerOnly();
1359 1372 }
1360 1373
1361 1374 return gotDouble ?
1362 1375 (Number)new Double(doubleResult) : (Number)new Long(longResult);
1363 1376 }
1364 1377 }
1365 1378
1366 1379 /**
1367 1380 * Return a BigInteger multiplier.
1368 1381 */
1369 1382 private BigInteger getBigIntegerMultiplier() {
1370 1383 if (bigIntegerMultiplier == null) {
1371 1384 bigIntegerMultiplier = BigInteger.valueOf(multiplier);
1372 1385 }
1373 1386 return bigIntegerMultiplier;
1374 1387 }
1375 1388 private transient BigInteger bigIntegerMultiplier;
1376 1389
1377 1390 /**
1378 1391 * Return a BigDecimal multiplier.
1379 1392 */
1380 1393 private BigDecimal getBigDecimalMultiplier() {
1381 1394 if (bigDecimalMultiplier == null) {
1382 1395 bigDecimalMultiplier = new BigDecimal(multiplier);
1383 1396 }
1384 1397 return bigDecimalMultiplier;
1385 1398 }
1386 1399 private transient BigDecimal bigDecimalMultiplier;
1387 1400
1388 1401 private static final int STATUS_INFINITE = 0;
1389 1402 private static final int STATUS_POSITIVE = 1;
1390 1403 private static final int STATUS_LENGTH = 2;
1391 1404
1392 1405 /**
1393 1406 * Parse the given text into a number. The text is parsed beginning at
1394 1407 * parsePosition, until an unparseable character is seen.
1395 1408 * @param text The string to parse.
1396 1409 * @param parsePosition The position at which to being parsing. Upon
1397 1410 * return, the first unparseable character.
1398 1411 * @param digits The DigitList to set to the parsed value.
1399 1412 * @param isExponent If true, parse an exponent. This means no
1400 1413 * infinite values and integer only.
1401 1414 * @param status Upon return contains boolean status flags indicating
1402 1415 * whether the value was infinite and whether it was positive.
1403 1416 */
1404 1417 private final boolean subparse(String text, ParsePosition parsePosition,
1405 1418 String positivePrefix, String negativePrefix,
1406 1419 DigitList digits, boolean isExponent,
1407 1420 boolean status[]) {
1408 1421 int position = parsePosition.index;
1409 1422 int oldStart = parsePosition.index;
1410 1423 int backup;
1411 1424 boolean gotPositive, gotNegative;
1412 1425
1413 1426 // check for positivePrefix; take longest
1414 1427 gotPositive = text.regionMatches(position, positivePrefix, 0,
1415 1428 positivePrefix.length());
1416 1429 gotNegative = text.regionMatches(position, negativePrefix, 0,
1417 1430 negativePrefix.length());
1418 1431
1419 1432 if (gotPositive && gotNegative) {
1420 1433 if (positivePrefix.length() > negativePrefix.length()) {
1421 1434 gotNegative = false;
1422 1435 } else if (positivePrefix.length() < negativePrefix.length()) {
1423 1436 gotPositive = false;
1424 1437 }
1425 1438 }
1426 1439
1427 1440 if (gotPositive) {
1428 1441 position += positivePrefix.length();
1429 1442 } else if (gotNegative) {
1430 1443 position += negativePrefix.length();
1431 1444 } else {
1432 1445 parsePosition.errorIndex = position;
1433 1446 return false;
1434 1447 }
1435 1448
1436 1449 // process digits or Inf, find decimal position
1437 1450 status[STATUS_INFINITE] = false;
1438 1451 if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
1439 1452 symbols.getInfinity().length())) {
1440 1453 position += symbols.getInfinity().length();
1441 1454 status[STATUS_INFINITE] = true;
1442 1455 } else {
1443 1456 // We now have a string of digits, possibly with grouping symbols,
1444 1457 // and decimal points. We want to process these into a DigitList.
1445 1458 // We don't want to put a bunch of leading zeros into the DigitList
1446 1459 // though, so we keep track of the location of the decimal point,
1447 1460 // put only significant digits into the DigitList, and adjust the
1448 1461 // exponent as needed.
1449 1462
1450 1463 digits.decimalAt = digits.count = 0;
1451 1464 char zero = symbols.getZeroDigit();
1452 1465 char decimal = isCurrencyFormat ?
1453 1466 symbols.getMonetaryDecimalSeparator() :
1454 1467 symbols.getDecimalSeparator();
1455 1468 char grouping = symbols.getGroupingSeparator();
1456 1469 String exponentString = symbols.getExponentSeparator();
1457 1470 boolean sawDecimal = false;
1458 1471 boolean sawExponent = false;
1459 1472 boolean sawDigit = false;
1460 1473 int exponent = 0; // Set to the exponent value, if any
1461 1474
1462 1475 // We have to track digitCount ourselves, because digits.count will
1463 1476 // pin when the maximum allowable digits is reached.
1464 1477 int digitCount = 0;
1465 1478
1466 1479 backup = -1;
1467 1480 for (; position < text.length(); ++position) {
1468 1481 char ch = text.charAt(position);
1469 1482
1470 1483 /* We recognize all digit ranges, not only the Latin digit range
1471 1484 * '0'..'9'. We do so by using the Character.digit() method,
1472 1485 * which converts a valid Unicode digit to the range 0..9.
1473 1486 *
1474 1487 * The character 'ch' may be a digit. If so, place its value
1475 1488 * from 0 to 9 in 'digit'. First try using the locale digit,
1476 1489 * which may or MAY NOT be a standard Unicode digit range. If
1477 1490 * this fails, try using the standard Unicode digit ranges by
1478 1491 * calling Character.digit(). If this also fails, digit will
1479 1492 * have a value outside the range 0..9.
1480 1493 */
1481 1494 int digit = ch - zero;
1482 1495 if (digit < 0 || digit > 9) {
1483 1496 digit = Character.digit(ch, 10);
1484 1497 }
1485 1498
1486 1499 if (digit == 0) {
1487 1500 // Cancel out backup setting (see grouping handler below)
1488 1501 backup = -1; // Do this BEFORE continue statement below!!!
1489 1502 sawDigit = true;
1490 1503
1491 1504 // Handle leading zeros
1492 1505 if (digits.count == 0) {
1493 1506 // Ignore leading zeros in integer part of number.
1494 1507 if (!sawDecimal) {
1495 1508 continue;
1496 1509 }
1497 1510
1498 1511 // If we have seen the decimal, but no significant
1499 1512 // digits yet, then we account for leading zeros by
1500 1513 // decrementing the digits.decimalAt into negative
1501 1514 // values.
1502 1515 --digits.decimalAt;
1503 1516 } else {
1504 1517 ++digitCount;
1505 1518 digits.append((char)(digit + '0'));
1506 1519 }
1507 1520 } else if (digit > 0 && digit <= 9) { // [sic] digit==0 handled above
1508 1521 sawDigit = true;
1509 1522 ++digitCount;
1510 1523 digits.append((char)(digit + '0'));
1511 1524
1512 1525 // Cancel out backup setting (see grouping handler below)
1513 1526 backup = -1;
1514 1527 } else if (!isExponent && ch == decimal) {
1515 1528 // If we're only parsing integers, or if we ALREADY saw the
1516 1529 // decimal, then don't parse this one.
1517 1530 if (isParseIntegerOnly() || sawDecimal) {
1518 1531 break;
1519 1532 }
1520 1533 digits.decimalAt = digitCount; // Not digits.count!
1521 1534 sawDecimal = true;
1522 1535 } else if (!isExponent && ch == grouping && isGroupingUsed()) {
1523 1536 if (sawDecimal) {
1524 1537 break;
1525 1538 }
1526 1539 // Ignore grouping characters, if we are using them, but
1527 1540 // require that they be followed by a digit. Otherwise
1528 1541 // we backup and reprocess them.
1529 1542 backup = position;
1530 1543 } else if (!isExponent && text.regionMatches(position, exponentString, 0, exponentString.length())
1531 1544 && !sawExponent) {
1532 1545 // Process the exponent by recursively calling this method.
1533 1546 ParsePosition pos = new ParsePosition(position + exponentString.length());
1534 1547 boolean[] stat = new boolean[STATUS_LENGTH];
1535 1548 DigitList exponentDigits = new DigitList();
1536 1549
1537 1550 if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
1538 1551 exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
1539 1552 position = pos.index; // Advance past the exponent
1540 1553 exponent = (int)exponentDigits.getLong();
1541 1554 if (!stat[STATUS_POSITIVE]) {
1542 1555 exponent = -exponent;
1543 1556 }
1544 1557 sawExponent = true;
1545 1558 }
1546 1559 break; // Whether we fail or succeed, we exit this loop
1547 1560 }
1548 1561 else {
1549 1562 break;
1550 1563 }
1551 1564 }
1552 1565
1553 1566 if (backup != -1) {
1554 1567 position = backup;
1555 1568 }
1556 1569
1557 1570 // If there was no decimal point we have an integer
1558 1571 if (!sawDecimal) {
1559 1572 digits.decimalAt = digitCount; // Not digits.count!
1560 1573 }
1561 1574
1562 1575 // Adjust for exponent, if any
1563 1576 digits.decimalAt += exponent;
1564 1577
1565 1578 // If none of the text string was recognized. For example, parse
1566 1579 // "x" with pattern "#0.00" (return index and error index both 0)
1567 1580 // parse "$" with pattern "$#0.00". (return index 0 and error
1568 1581 // index 1).
1569 1582 if (!sawDigit && digitCount == 0) {
1570 1583 parsePosition.index = oldStart;
1571 1584 parsePosition.errorIndex = oldStart;
1572 1585 return false;
1573 1586 }
1574 1587 }
1575 1588
1576 1589 // check for suffix
1577 1590 if (!isExponent) {
1578 1591 if (gotPositive) {
1579 1592 gotPositive = text.regionMatches(position,positiveSuffix,0,
1580 1593 positiveSuffix.length());
1581 1594 }
1582 1595 if (gotNegative) {
1583 1596 gotNegative = text.regionMatches(position,negativeSuffix,0,
1584 1597 negativeSuffix.length());
1585 1598 }
1586 1599
1587 1600 // if both match, take longest
1588 1601 if (gotPositive && gotNegative) {
1589 1602 if (positiveSuffix.length() > negativeSuffix.length()) {
1590 1603 gotNegative = false;
1591 1604 } else if (positiveSuffix.length() < negativeSuffix.length()) {
1592 1605 gotPositive = false;
1593 1606 }
1594 1607 }
1595 1608
1596 1609 // fail if neither or both
1597 1610 if (gotPositive == gotNegative) {
1598 1611 parsePosition.errorIndex = position;
1599 1612 return false;
1600 1613 }
1601 1614
1602 1615 parsePosition.index = position +
1603 1616 (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
1604 1617 } else {
1605 1618 parsePosition.index = position;
1606 1619 }
1607 1620
1608 1621 status[STATUS_POSITIVE] = gotPositive;
1609 1622 if (parsePosition.index == oldStart) {
1610 1623 parsePosition.errorIndex = position;
1611 1624 return false;
1612 1625 }
1613 1626 return true;
1614 1627 }
1615 1628
1616 1629 /**
1617 1630 * Returns a copy of the decimal format symbols, which is generally not
1618 1631 * changed by the programmer or user.
1619 1632 * @return a copy of the desired DecimalFormatSymbols
1620 1633 * @see java.text.DecimalFormatSymbols
1621 1634 */
1622 1635 public DecimalFormatSymbols getDecimalFormatSymbols() {
1623 1636 try {
1624 1637 // don't allow multiple references
1625 1638 return (DecimalFormatSymbols) symbols.clone();
1626 1639 } catch (Exception foo) {
1627 1640 return null; // should never happen
1628 1641 }
1629 1642 }
1630 1643
1631 1644
1632 1645 /**
1633 1646 * Sets the decimal format symbols, which is generally not changed
1634 1647 * by the programmer or user.
1635 1648 * @param newSymbols desired DecimalFormatSymbols
1636 1649 * @see java.text.DecimalFormatSymbols
1637 1650 */
1638 1651 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
1639 1652 try {
1640 1653 // don't allow multiple references
1641 1654 symbols = (DecimalFormatSymbols) newSymbols.clone();
1642 1655 expandAffixes();
1643 1656 } catch (Exception foo) {
1644 1657 // should never happen
1645 1658 }
1646 1659 }
1647 1660
1648 1661 /**
1649 1662 * Get the positive prefix.
1650 1663 * <P>Examples: +123, $123, sFr123
1651 1664 */
1652 1665 public String getPositivePrefix () {
1653 1666 return positivePrefix;
1654 1667 }
1655 1668
1656 1669 /**
1657 1670 * Set the positive prefix.
1658 1671 * <P>Examples: +123, $123, sFr123
1659 1672 */
1660 1673 public void setPositivePrefix (String newValue) {
1661 1674 positivePrefix = newValue;
1662 1675 posPrefixPattern = null;
1663 1676 positivePrefixFieldPositions = null;
1664 1677 }
1665 1678
1666 1679 /**
1667 1680 * Returns the FieldPositions of the fields in the prefix used for
1668 1681 * positive numbers. This is not used if the user has explicitly set
1669 1682 * a positive prefix via <code>setPositivePrefix</code>. This is
1670 1683 * lazily created.
1671 1684 *
1672 1685 * @return FieldPositions in positive prefix
1673 1686 */
1674 1687 private FieldPosition[] getPositivePrefixFieldPositions() {
1675 1688 if (positivePrefixFieldPositions == null) {
1676 1689 if (posPrefixPattern != null) {
1677 1690 positivePrefixFieldPositions = expandAffix(posPrefixPattern);
1678 1691 }
1679 1692 else {
1680 1693 positivePrefixFieldPositions = EmptyFieldPositionArray;
1681 1694 }
1682 1695 }
1683 1696 return positivePrefixFieldPositions;
1684 1697 }
1685 1698
1686 1699 /**
1687 1700 * Get the negative prefix.
1688 1701 * <P>Examples: -123, ($123) (with negative suffix), sFr-123
1689 1702 */
1690 1703 public String getNegativePrefix () {
1691 1704 return negativePrefix;
1692 1705 }
1693 1706
1694 1707 /**
1695 1708 * Set the negative prefix.
1696 1709 * <P>Examples: -123, ($123) (with negative suffix), sFr-123
1697 1710 */
1698 1711 public void setNegativePrefix (String newValue) {
1699 1712 negativePrefix = newValue;
1700 1713 negPrefixPattern = null;
1701 1714 }
1702 1715
1703 1716 /**
1704 1717 * Returns the FieldPositions of the fields in the prefix used for
1705 1718 * negative numbers. This is not used if the user has explicitly set
1706 1719 * a negative prefix via <code>setNegativePrefix</code>. This is
1707 1720 * lazily created.
1708 1721 *
1709 1722 * @return FieldPositions in positive prefix
1710 1723 */
1711 1724 private FieldPosition[] getNegativePrefixFieldPositions() {
1712 1725 if (negativePrefixFieldPositions == null) {
1713 1726 if (negPrefixPattern != null) {
1714 1727 negativePrefixFieldPositions = expandAffix(negPrefixPattern);
1715 1728 }
1716 1729 else {
1717 1730 negativePrefixFieldPositions = EmptyFieldPositionArray;
1718 1731 }
1719 1732 }
1720 1733 return negativePrefixFieldPositions;
1721 1734 }
1722 1735
1723 1736 /**
1724 1737 * Get the positive suffix.
1725 1738 * <P>Example: 123%
1726 1739 */
1727 1740 public String getPositiveSuffix () {
1728 1741 return positiveSuffix;
1729 1742 }
1730 1743
1731 1744 /**
1732 1745 * Set the positive suffix.
1733 1746 * <P>Example: 123%
1734 1747 */
1735 1748 public void setPositiveSuffix (String newValue) {
1736 1749 positiveSuffix = newValue;
1737 1750 posSuffixPattern = null;
1738 1751 }
1739 1752
1740 1753 /**
1741 1754 * Returns the FieldPositions of the fields in the suffix used for
1742 1755 * positive numbers. This is not used if the user has explicitly set
1743 1756 * a positive suffix via <code>setPositiveSuffix</code>. This is
1744 1757 * lazily created.
1745 1758 *
1746 1759 * @return FieldPositions in positive prefix
1747 1760 */
1748 1761 private FieldPosition[] getPositiveSuffixFieldPositions() {
1749 1762 if (positiveSuffixFieldPositions == null) {
1750 1763 if (posSuffixPattern != null) {
1751 1764 positiveSuffixFieldPositions = expandAffix(posSuffixPattern);
1752 1765 }
1753 1766 else {
1754 1767 positiveSuffixFieldPositions = EmptyFieldPositionArray;
1755 1768 }
1756 1769 }
1757 1770 return positiveSuffixFieldPositions;
1758 1771 }
1759 1772
1760 1773 /**
1761 1774 * Get the negative suffix.
1762 1775 * <P>Examples: -123%, ($123) (with positive suffixes)
1763 1776 */
1764 1777 public String getNegativeSuffix () {
1765 1778 return negativeSuffix;
1766 1779 }
1767 1780
1768 1781 /**
1769 1782 * Set the negative suffix.
1770 1783 * <P>Examples: 123%
1771 1784 */
1772 1785 public void setNegativeSuffix (String newValue) {
1773 1786 negativeSuffix = newValue;
1774 1787 negSuffixPattern = null;
1775 1788 }
1776 1789
1777 1790 /**
1778 1791 * Returns the FieldPositions of the fields in the suffix used for
1779 1792 * negative numbers. This is not used if the user has explicitly set
1780 1793 * a negative suffix via <code>setNegativeSuffix</code>. This is
1781 1794 * lazily created.
1782 1795 *
1783 1796 * @return FieldPositions in positive prefix
1784 1797 */
1785 1798 private FieldPosition[] getNegativeSuffixFieldPositions() {
1786 1799 if (negativeSuffixFieldPositions == null) {
1787 1800 if (negSuffixPattern != null) {
1788 1801 negativeSuffixFieldPositions = expandAffix(negSuffixPattern);
1789 1802 }
1790 1803 else {
1791 1804 negativeSuffixFieldPositions = EmptyFieldPositionArray;
1792 1805 }
1793 1806 }
1794 1807 return negativeSuffixFieldPositions;
1795 1808 }
1796 1809
1797 1810 /**
1798 1811 * Gets the multiplier for use in percent, per mille, and similar
1799 1812 * formats.
1800 1813 *
1801 1814 * @see #setMultiplier(int)
1802 1815 */
1803 1816 public int getMultiplier () {
1804 1817 return multiplier;
1805 1818 }
1806 1819
1807 1820 /**
1808 1821 * Sets the multiplier for use in percent, per mille, and similar
1809 1822 * formats.
1810 1823 * For a percent format, set the multiplier to 100 and the suffixes to
1811 1824 * have '%' (for Arabic, use the Arabic percent sign).
1812 1825 * For a per mille format, set the multiplier to 1000 and the suffixes to
1813 1826 * have '\u2030'.
1814 1827 *
1815 1828 * <P>Example: with multiplier 100, 1.23 is formatted as "123", and
1816 1829 * "123" is parsed into 1.23.
1817 1830 *
1818 1831 * @see #getMultiplier
1819 1832 */
1820 1833 public void setMultiplier (int newValue) {
1821 1834 multiplier = newValue;
1822 1835 bigDecimalMultiplier = null;
1823 1836 bigIntegerMultiplier = null;
1824 1837 }
1825 1838
1826 1839 /**
1827 1840 * Return the grouping size. Grouping size is the number of digits between
1828 1841 * grouping separators in the integer portion of a number. For example,
1829 1842 * in the number "123,456.78", the grouping size is 3.
1830 1843 * @see #setGroupingSize
1831 1844 * @see java.text.NumberFormat#isGroupingUsed
1832 1845 * @see java.text.DecimalFormatSymbols#getGroupingSeparator
1833 1846 */
1834 1847 public int getGroupingSize () {
1835 1848 return groupingSize;
1836 1849 }
1837 1850
1838 1851 /**
1839 1852 * Set the grouping size. Grouping size is the number of digits between
1840 1853 * grouping separators in the integer portion of a number. For example,
1841 1854 * in the number "123,456.78", the grouping size is 3.
1842 1855 * <br>
1843 1856 * The value passed in is converted to a byte, which may lose information.
1844 1857 * @see #getGroupingSize
1845 1858 * @see java.text.NumberFormat#setGroupingUsed
1846 1859 * @see java.text.DecimalFormatSymbols#setGroupingSeparator
1847 1860 */
1848 1861 public void setGroupingSize (int newValue) {
1849 1862 groupingSize = (byte)newValue;
1850 1863 }
1851 1864
1852 1865 /**
1853 1866 * Allows you to get the behavior of the decimal separator with integers.
1854 1867 * (The decimal separator will always appear with decimals.)
1855 1868 * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
1856 1869 */
1857 1870 public boolean isDecimalSeparatorAlwaysShown() {
1858 1871 return decimalSeparatorAlwaysShown;
1859 1872 }
1860 1873
1861 1874 /**
1862 1875 * Allows you to set the behavior of the decimal separator with integers.
1863 1876 * (The decimal separator will always appear with decimals.)
1864 1877 * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
1865 1878 */
1866 1879 public void setDecimalSeparatorAlwaysShown(boolean newValue) {
1867 1880 decimalSeparatorAlwaysShown = newValue;
1868 1881 }
1869 1882
1870 1883 /**
1871 1884 * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
1872 1885 * method returns <code>BigDecimal</code>. The default value is false.
1873 1886 * @see #setParseBigDecimal
1874 1887 * @since 1.5
1875 1888 */
1876 1889 public boolean isParseBigDecimal() {
1877 1890 return parseBigDecimal;
1878 1891 }
1879 1892
1880 1893 /**
1881 1894 * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
1882 1895 * method returns <code>BigDecimal</code>.
↓ open down ↓ |
613 lines elided |
↑ open up ↑ |
1883 1896 * @see #isParseBigDecimal
1884 1897 * @since 1.5
1885 1898 */
1886 1899 public void setParseBigDecimal(boolean newValue) {
1887 1900 parseBigDecimal = newValue;
1888 1901 }
1889 1902
1890 1903 /**
1891 1904 * Standard override; no change in semantics.
1892 1905 */
1906 + @Override
1893 1907 public Object clone() {
1894 1908 DecimalFormat other = (DecimalFormat) super.clone();
1895 1909 other.symbols = (DecimalFormatSymbols) symbols.clone();
1896 1910 other.digitList = (DigitList) digitList.clone();
1897 1911 return other;
1898 1912 }
1899 1913
1900 1914 /**
1901 1915 * Overrides equals
1902 1916 */
1917 + @Override
1903 1918 public boolean equals(Object obj)
1904 1919 {
1905 1920 if (obj == null) return false;
1906 1921 if (!super.equals(obj)) return false; // super does class check
1907 1922 DecimalFormat other = (DecimalFormat) obj;
1908 1923 return ((posPrefixPattern == other.posPrefixPattern &&
1909 1924 positivePrefix.equals(other.positivePrefix))
1910 1925 || (posPrefixPattern != null &&
1911 1926 posPrefixPattern.equals(other.posPrefixPattern)))
1912 1927 && ((posSuffixPattern == other.posSuffixPattern &&
1913 1928 positiveSuffix.equals(other.positiveSuffix))
1914 1929 || (posSuffixPattern != null &&
1915 1930 posSuffixPattern.equals(other.posSuffixPattern)))
1916 1931 && ((negPrefixPattern == other.negPrefixPattern &&
1917 1932 negativePrefix.equals(other.negativePrefix))
1918 1933 || (negPrefixPattern != null &&
1919 1934 negPrefixPattern.equals(other.negPrefixPattern)))
1920 1935 && ((negSuffixPattern == other.negSuffixPattern &&
1921 1936 negativeSuffix.equals(other.negativeSuffix))
1922 1937 || (negSuffixPattern != null &&
1923 1938 negSuffixPattern.equals(other.negSuffixPattern)))
1924 1939 && multiplier == other.multiplier
1925 1940 && groupingSize == other.groupingSize
1926 1941 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
1927 1942 && parseBigDecimal == other.parseBigDecimal
1928 1943 && useExponentialNotation == other.useExponentialNotation
1929 1944 && (!useExponentialNotation ||
1930 1945 minExponentDigits == other.minExponentDigits)
1931 1946 && maximumIntegerDigits == other.maximumIntegerDigits
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
1932 1947 && minimumIntegerDigits == other.minimumIntegerDigits
1933 1948 && maximumFractionDigits == other.maximumFractionDigits
1934 1949 && minimumFractionDigits == other.minimumFractionDigits
1935 1950 && roundingMode == other.roundingMode
1936 1951 && symbols.equals(other.symbols);
1937 1952 }
1938 1953
1939 1954 /**
1940 1955 * Overrides hashCode
1941 1956 */
1957 + @Override
1942 1958 public int hashCode() {
1943 1959 return super.hashCode() * 37 + positivePrefix.hashCode();
1944 1960 // just enough fields for a reasonable distribution
1945 1961 }
1946 1962
1947 1963 /**
1948 1964 * Synthesizes a pattern string that represents the current state
1949 1965 * of this Format object.
1950 1966 * @see #applyPattern
1951 1967 */
1952 1968 public String toPattern() {
1953 1969 return toPattern( false );
1954 1970 }
1955 1971
1956 1972 /**
1957 1973 * Synthesizes a localized pattern string that represents the current
1958 1974 * state of this Format object.
1959 1975 * @see #applyPattern
1960 1976 */
1961 1977 public String toLocalizedPattern() {
1962 1978 return toPattern( true );
1963 1979 }
1964 1980
1965 1981 /**
1966 1982 * Expand the affix pattern strings into the expanded affix strings. If any
1967 1983 * affix pattern string is null, do not expand it. This method should be
1968 1984 * called any time the symbols or the affix patterns change in order to keep
1969 1985 * the expanded affix strings up to date.
1970 1986 */
1971 1987 private void expandAffixes() {
1972 1988 // Reuse one StringBuffer for better performance
1973 1989 StringBuffer buffer = new StringBuffer();
1974 1990 if (posPrefixPattern != null) {
1975 1991 positivePrefix = expandAffix(posPrefixPattern, buffer);
1976 1992 positivePrefixFieldPositions = null;
1977 1993 }
1978 1994 if (posSuffixPattern != null) {
1979 1995 positiveSuffix = expandAffix(posSuffixPattern, buffer);
1980 1996 positiveSuffixFieldPositions = null;
1981 1997 }
1982 1998 if (negPrefixPattern != null) {
1983 1999 negativePrefix = expandAffix(negPrefixPattern, buffer);
1984 2000 negativePrefixFieldPositions = null;
1985 2001 }
1986 2002 if (negSuffixPattern != null) {
1987 2003 negativeSuffix = expandAffix(negSuffixPattern, buffer);
1988 2004 negativeSuffixFieldPositions = null;
1989 2005 }
1990 2006 }
1991 2007
1992 2008 /**
1993 2009 * Expand an affix pattern into an affix string. All characters in the
1994 2010 * pattern are literal unless prefixed by QUOTE. The following characters
1995 2011 * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
1996 2012 * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
1997 2013 * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
1998 2014 * currency code. Any other character after a QUOTE represents itself.
1999 2015 * QUOTE must be followed by another character; QUOTE may not occur by
2000 2016 * itself at the end of the pattern.
2001 2017 *
2002 2018 * @param pattern the non-null, possibly empty pattern
2003 2019 * @param buffer a scratch StringBuffer; its contents will be lost
2004 2020 * @return the expanded equivalent of pattern
2005 2021 */
2006 2022 private String expandAffix(String pattern, StringBuffer buffer) {
2007 2023 buffer.setLength(0);
2008 2024 for (int i=0; i<pattern.length(); ) {
2009 2025 char c = pattern.charAt(i++);
2010 2026 if (c == QUOTE) {
2011 2027 c = pattern.charAt(i++);
2012 2028 switch (c) {
2013 2029 case CURRENCY_SIGN:
2014 2030 if (i<pattern.length() &&
2015 2031 pattern.charAt(i) == CURRENCY_SIGN) {
2016 2032 ++i;
2017 2033 buffer.append(symbols.getInternationalCurrencySymbol());
2018 2034 } else {
2019 2035 buffer.append(symbols.getCurrencySymbol());
2020 2036 }
2021 2037 continue;
2022 2038 case PATTERN_PERCENT:
2023 2039 c = symbols.getPercent();
2024 2040 break;
2025 2041 case PATTERN_PER_MILLE:
2026 2042 c = symbols.getPerMill();
2027 2043 break;
2028 2044 case PATTERN_MINUS:
2029 2045 c = symbols.getMinusSign();
2030 2046 break;
2031 2047 }
2032 2048 }
2033 2049 buffer.append(c);
2034 2050 }
2035 2051 return buffer.toString();
2036 2052 }
2037 2053
2038 2054 /**
2039 2055 * Expand an affix pattern into an array of FieldPositions describing
2040 2056 * how the pattern would be expanded.
2041 2057 * All characters in the
2042 2058 * pattern are literal unless prefixed by QUOTE. The following characters
2043 2059 * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
2044 2060 * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
2045 2061 * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an ISO 4217
2046 2062 * currency code. Any other character after a QUOTE represents itself.
2047 2063 * QUOTE must be followed by another character; QUOTE may not occur by
2048 2064 * itself at the end of the pattern.
2049 2065 *
2050 2066 * @param pattern the non-null, possibly empty pattern
2051 2067 * @return FieldPosition array of the resulting fields.
2052 2068 */
2053 2069 private FieldPosition[] expandAffix(String pattern) {
2054 2070 ArrayList<FieldPosition> positions = null;
2055 2071 int stringIndex = 0;
2056 2072 for (int i=0; i<pattern.length(); ) {
2057 2073 char c = pattern.charAt(i++);
2058 2074 if (c == QUOTE) {
2059 2075 int field = -1;
2060 2076 Format.Field fieldID = null;
2061 2077 c = pattern.charAt(i++);
2062 2078 switch (c) {
2063 2079 case CURRENCY_SIGN:
2064 2080 String string;
2065 2081 if (i<pattern.length() &&
2066 2082 pattern.charAt(i) == CURRENCY_SIGN) {
2067 2083 ++i;
2068 2084 string = symbols.getInternationalCurrencySymbol();
2069 2085 } else {
2070 2086 string = symbols.getCurrencySymbol();
2071 2087 }
2072 2088 if (string.length() > 0) {
2073 2089 if (positions == null) {
2074 2090 positions = new ArrayList<>(2);
2075 2091 }
2076 2092 FieldPosition fp = new FieldPosition(Field.CURRENCY);
2077 2093 fp.setBeginIndex(stringIndex);
2078 2094 fp.setEndIndex(stringIndex + string.length());
2079 2095 positions.add(fp);
2080 2096 stringIndex += string.length();
2081 2097 }
2082 2098 continue;
2083 2099 case PATTERN_PERCENT:
2084 2100 c = symbols.getPercent();
2085 2101 field = -1;
2086 2102 fieldID = Field.PERCENT;
2087 2103 break;
2088 2104 case PATTERN_PER_MILLE:
2089 2105 c = symbols.getPerMill();
2090 2106 field = -1;
2091 2107 fieldID = Field.PERMILLE;
2092 2108 break;
2093 2109 case PATTERN_MINUS:
2094 2110 c = symbols.getMinusSign();
2095 2111 field = -1;
2096 2112 fieldID = Field.SIGN;
2097 2113 break;
2098 2114 }
2099 2115 if (fieldID != null) {
2100 2116 if (positions == null) {
2101 2117 positions = new ArrayList<>(2);
2102 2118 }
2103 2119 FieldPosition fp = new FieldPosition(fieldID, field);
2104 2120 fp.setBeginIndex(stringIndex);
2105 2121 fp.setEndIndex(stringIndex + 1);
2106 2122 positions.add(fp);
2107 2123 }
2108 2124 }
2109 2125 stringIndex++;
2110 2126 }
2111 2127 if (positions != null) {
2112 2128 return positions.toArray(EmptyFieldPositionArray);
2113 2129 }
2114 2130 return EmptyFieldPositionArray;
2115 2131 }
2116 2132
2117 2133 /**
2118 2134 * Appends an affix pattern to the given StringBuffer, quoting special
2119 2135 * characters as needed. Uses the internal affix pattern, if that exists,
2120 2136 * or the literal affix, if the internal affix pattern is null. The
2121 2137 * appended string will generate the same affix pattern (or literal affix)
2122 2138 * when passed to toPattern().
2123 2139 *
2124 2140 * @param buffer the affix string is appended to this
2125 2141 * @param affixPattern a pattern such as posPrefixPattern; may be null
2126 2142 * @param expAffix a corresponding expanded affix, such as positivePrefix.
2127 2143 * Ignored unless affixPattern is null. If affixPattern is null, then
2128 2144 * expAffix is appended as a literal affix.
2129 2145 * @param localized true if the appended pattern should contain localized
2130 2146 * pattern characters; otherwise, non-localized pattern chars are appended
2131 2147 */
2132 2148 private void appendAffix(StringBuffer buffer, String affixPattern,
2133 2149 String expAffix, boolean localized) {
2134 2150 if (affixPattern == null) {
2135 2151 appendAffix(buffer, expAffix, localized);
2136 2152 } else {
2137 2153 int i;
2138 2154 for (int pos=0; pos<affixPattern.length(); pos=i) {
2139 2155 i = affixPattern.indexOf(QUOTE, pos);
2140 2156 if (i < 0) {
2141 2157 appendAffix(buffer, affixPattern.substring(pos), localized);
2142 2158 break;
2143 2159 }
2144 2160 if (i > pos) {
2145 2161 appendAffix(buffer, affixPattern.substring(pos, i), localized);
2146 2162 }
2147 2163 char c = affixPattern.charAt(++i);
2148 2164 ++i;
2149 2165 if (c == QUOTE) {
2150 2166 buffer.append(c);
2151 2167 // Fall through and append another QUOTE below
2152 2168 } else if (c == CURRENCY_SIGN &&
2153 2169 i<affixPattern.length() &&
2154 2170 affixPattern.charAt(i) == CURRENCY_SIGN) {
2155 2171 ++i;
2156 2172 buffer.append(c);
2157 2173 // Fall through and append another CURRENCY_SIGN below
2158 2174 } else if (localized) {
2159 2175 switch (c) {
2160 2176 case PATTERN_PERCENT:
2161 2177 c = symbols.getPercent();
2162 2178 break;
2163 2179 case PATTERN_PER_MILLE:
2164 2180 c = symbols.getPerMill();
2165 2181 break;
2166 2182 case PATTERN_MINUS:
2167 2183 c = symbols.getMinusSign();
2168 2184 break;
2169 2185 }
2170 2186 }
2171 2187 buffer.append(c);
2172 2188 }
2173 2189 }
2174 2190 }
2175 2191
2176 2192 /**
2177 2193 * Append an affix to the given StringBuffer, using quotes if
2178 2194 * there are special characters. Single quotes themselves must be
2179 2195 * escaped in either case.
2180 2196 */
2181 2197 private void appendAffix(StringBuffer buffer, String affix, boolean localized) {
2182 2198 boolean needQuote;
2183 2199 if (localized) {
2184 2200 needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
2185 2201 || affix.indexOf(symbols.getGroupingSeparator()) >= 0
2186 2202 || affix.indexOf(symbols.getDecimalSeparator()) >= 0
2187 2203 || affix.indexOf(symbols.getPercent()) >= 0
2188 2204 || affix.indexOf(symbols.getPerMill()) >= 0
2189 2205 || affix.indexOf(symbols.getDigit()) >= 0
2190 2206 || affix.indexOf(symbols.getPatternSeparator()) >= 0
2191 2207 || affix.indexOf(symbols.getMinusSign()) >= 0
2192 2208 || affix.indexOf(CURRENCY_SIGN) >= 0;
2193 2209 }
2194 2210 else {
2195 2211 needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
2196 2212 || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
2197 2213 || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
2198 2214 || affix.indexOf(PATTERN_PERCENT) >= 0
2199 2215 || affix.indexOf(PATTERN_PER_MILLE) >= 0
2200 2216 || affix.indexOf(PATTERN_DIGIT) >= 0
2201 2217 || affix.indexOf(PATTERN_SEPARATOR) >= 0
2202 2218 || affix.indexOf(PATTERN_MINUS) >= 0
2203 2219 || affix.indexOf(CURRENCY_SIGN) >= 0;
2204 2220 }
2205 2221 if (needQuote) buffer.append('\'');
2206 2222 if (affix.indexOf('\'') < 0) buffer.append(affix);
2207 2223 else {
2208 2224 for (int j=0; j<affix.length(); ++j) {
2209 2225 char c = affix.charAt(j);
2210 2226 buffer.append(c);
2211 2227 if (c == '\'') buffer.append(c);
2212 2228 }
2213 2229 }
2214 2230 if (needQuote) buffer.append('\'');
2215 2231 }
2216 2232
2217 2233 /**
2218 2234 * Does the real work of generating a pattern. */
2219 2235 private String toPattern(boolean localized) {
2220 2236 StringBuffer result = new StringBuffer();
2221 2237 for (int j = 1; j >= 0; --j) {
2222 2238 if (j == 1)
2223 2239 appendAffix(result, posPrefixPattern, positivePrefix, localized);
2224 2240 else appendAffix(result, negPrefixPattern, negativePrefix, localized);
2225 2241 int i;
2226 2242 int digitCount = useExponentialNotation
2227 2243 ? getMaximumIntegerDigits()
2228 2244 : Math.max(groupingSize, getMinimumIntegerDigits())+1;
2229 2245 for (i = digitCount; i > 0; --i) {
2230 2246 if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&
2231 2247 i % groupingSize == 0) {
2232 2248 result.append(localized ? symbols.getGroupingSeparator() :
2233 2249 PATTERN_GROUPING_SEPARATOR);
2234 2250 }
2235 2251 result.append(i <= getMinimumIntegerDigits()
2236 2252 ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)
2237 2253 : (localized ? symbols.getDigit() : PATTERN_DIGIT));
2238 2254 }
2239 2255 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)
2240 2256 result.append(localized ? symbols.getDecimalSeparator() :
2241 2257 PATTERN_DECIMAL_SEPARATOR);
2242 2258 for (i = 0; i < getMaximumFractionDigits(); ++i) {
2243 2259 if (i < getMinimumFractionDigits()) {
2244 2260 result.append(localized ? symbols.getZeroDigit() :
2245 2261 PATTERN_ZERO_DIGIT);
2246 2262 } else {
2247 2263 result.append(localized ? symbols.getDigit() :
2248 2264 PATTERN_DIGIT);
2249 2265 }
2250 2266 }
2251 2267 if (useExponentialNotation)
2252 2268 {
2253 2269 result.append(localized ? symbols.getExponentSeparator() :
2254 2270 PATTERN_EXPONENT);
2255 2271 for (i=0; i<minExponentDigits; ++i)
2256 2272 result.append(localized ? symbols.getZeroDigit() :
2257 2273 PATTERN_ZERO_DIGIT);
2258 2274 }
2259 2275 if (j == 1) {
2260 2276 appendAffix(result, posSuffixPattern, positiveSuffix, localized);
2261 2277 if ((negSuffixPattern == posSuffixPattern && // n == p == null
2262 2278 negativeSuffix.equals(positiveSuffix))
2263 2279 || (negSuffixPattern != null &&
2264 2280 negSuffixPattern.equals(posSuffixPattern))) {
2265 2281 if ((negPrefixPattern != null && posPrefixPattern != null &&
2266 2282 negPrefixPattern.equals("'-" + posPrefixPattern)) ||
2267 2283 (negPrefixPattern == posPrefixPattern && // n == p == null
2268 2284 negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
2269 2285 break;
2270 2286 }
2271 2287 result.append(localized ? symbols.getPatternSeparator() :
2272 2288 PATTERN_SEPARATOR);
2273 2289 } else appendAffix(result, negSuffixPattern, negativeSuffix, localized);
2274 2290 }
2275 2291 return result.toString();
2276 2292 }
2277 2293
2278 2294 /**
2279 2295 * Apply the given pattern to this Format object. A pattern is a
2280 2296 * short-hand specification for the various formatting properties.
2281 2297 * These properties can also be changed individually through the
2282 2298 * various setter methods.
2283 2299 * <p>
2284 2300 * There is no limit to integer digits set
2285 2301 * by this routine, since that is the typical end-user desire;
2286 2302 * use setMaximumInteger if you want to set a real value.
2287 2303 * For negative numbers, use a second pattern, separated by a semicolon
2288 2304 * <P>Example <code>"#,#00.0#"</code> -> 1,234.56
2289 2305 * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
2290 2306 * a maximum of 2 fraction digits.
2291 2307 * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
2292 2308 * parentheses.
2293 2309 * <p>In negative patterns, the minimum and maximum counts are ignored;
2294 2310 * these are presumed to be set in the positive pattern.
2295 2311 *
2296 2312 * @exception NullPointerException if <code>pattern</code> is null
2297 2313 * @exception IllegalArgumentException if the given pattern is invalid.
2298 2314 */
2299 2315 public void applyPattern(String pattern) {
2300 2316 applyPattern(pattern, false);
2301 2317 }
2302 2318
2303 2319 /**
2304 2320 * Apply the given pattern to this Format object. The pattern
2305 2321 * is assumed to be in a localized notation. A pattern is a
2306 2322 * short-hand specification for the various formatting properties.
2307 2323 * These properties can also be changed individually through the
2308 2324 * various setter methods.
2309 2325 * <p>
2310 2326 * There is no limit to integer digits set
2311 2327 * by this routine, since that is the typical end-user desire;
2312 2328 * use setMaximumInteger if you want to set a real value.
2313 2329 * For negative numbers, use a second pattern, separated by a semicolon
2314 2330 * <P>Example <code>"#,#00.0#"</code> -> 1,234.56
2315 2331 * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
2316 2332 * a maximum of 2 fraction digits.
2317 2333 * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
2318 2334 * parentheses.
2319 2335 * <p>In negative patterns, the minimum and maximum counts are ignored;
2320 2336 * these are presumed to be set in the positive pattern.
2321 2337 *
2322 2338 * @exception NullPointerException if <code>pattern</code> is null
2323 2339 * @exception IllegalArgumentException if the given pattern is invalid.
2324 2340 */
2325 2341 public void applyLocalizedPattern(String pattern) {
2326 2342 applyPattern(pattern, true);
2327 2343 }
2328 2344
2329 2345 /**
2330 2346 * Does the real work of applying a pattern.
2331 2347 */
2332 2348 private void applyPattern(String pattern, boolean localized) {
2333 2349 char zeroDigit = PATTERN_ZERO_DIGIT;
2334 2350 char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
2335 2351 char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
2336 2352 char percent = PATTERN_PERCENT;
2337 2353 char perMill = PATTERN_PER_MILLE;
2338 2354 char digit = PATTERN_DIGIT;
2339 2355 char separator = PATTERN_SEPARATOR;
2340 2356 String exponent = PATTERN_EXPONENT;
2341 2357 char minus = PATTERN_MINUS;
2342 2358 if (localized) {
2343 2359 zeroDigit = symbols.getZeroDigit();
2344 2360 groupingSeparator = symbols.getGroupingSeparator();
2345 2361 decimalSeparator = symbols.getDecimalSeparator();
2346 2362 percent = symbols.getPercent();
2347 2363 perMill = symbols.getPerMill();
2348 2364 digit = symbols.getDigit();
2349 2365 separator = symbols.getPatternSeparator();
2350 2366 exponent = symbols.getExponentSeparator();
2351 2367 minus = symbols.getMinusSign();
2352 2368 }
2353 2369 boolean gotNegative = false;
2354 2370 decimalSeparatorAlwaysShown = false;
2355 2371 isCurrencyFormat = false;
2356 2372 useExponentialNotation = false;
2357 2373
2358 2374 // Two variables are used to record the subrange of the pattern
2359 2375 // occupied by phase 1. This is used during the processing of the
2360 2376 // second pattern (the one representing negative numbers) to ensure
2361 2377 // that no deviation exists in phase 1 between the two patterns.
2362 2378 int phaseOneStart = 0;
2363 2379 int phaseOneLength = 0;
2364 2380
2365 2381 int start = 0;
2366 2382 for (int j = 1; j >= 0 && start < pattern.length(); --j) {
2367 2383 boolean inQuote = false;
2368 2384 StringBuffer prefix = new StringBuffer();
2369 2385 StringBuffer suffix = new StringBuffer();
2370 2386 int decimalPos = -1;
2371 2387 int multiplier = 1;
2372 2388 int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
2373 2389 byte groupingCount = -1;
2374 2390
2375 2391 // The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is
2376 2392 // the section of the pattern with digits, decimal separator,
2377 2393 // grouping characters. Phase 2 is the suffix. In phases 0 and 2,
2378 2394 // percent, per mille, and currency symbols are recognized and
2379 2395 // translated. The separation of the characters into phases is
2380 2396 // strictly enforced; if phase 1 characters are to appear in the
2381 2397 // suffix, for example, they must be quoted.
2382 2398 int phase = 0;
2383 2399
2384 2400 // The affix is either the prefix or the suffix.
2385 2401 StringBuffer affix = prefix;
2386 2402
2387 2403 for (int pos = start; pos < pattern.length(); ++pos) {
2388 2404 char ch = pattern.charAt(pos);
2389 2405 switch (phase) {
2390 2406 case 0:
2391 2407 case 2:
2392 2408 // Process the prefix / suffix characters
2393 2409 if (inQuote) {
2394 2410 // A quote within quotes indicates either the closing
2395 2411 // quote or two quotes, which is a quote literal. That
2396 2412 // is, we have the second quote in 'do' or 'don''t'.
2397 2413 if (ch == QUOTE) {
2398 2414 if ((pos+1) < pattern.length() &&
2399 2415 pattern.charAt(pos+1) == QUOTE) {
2400 2416 ++pos;
2401 2417 affix.append("''"); // 'don''t'
2402 2418 } else {
2403 2419 inQuote = false; // 'do'
2404 2420 }
2405 2421 continue;
2406 2422 }
2407 2423 } else {
2408 2424 // Process unquoted characters seen in prefix or suffix
2409 2425 // phase.
2410 2426 if (ch == digit ||
2411 2427 ch == zeroDigit ||
2412 2428 ch == groupingSeparator ||
2413 2429 ch == decimalSeparator) {
2414 2430 phase = 1;
2415 2431 if (j == 1) {
2416 2432 phaseOneStart = pos;
2417 2433 }
2418 2434 --pos; // Reprocess this character
2419 2435 continue;
2420 2436 } else if (ch == CURRENCY_SIGN) {
2421 2437 // Use lookahead to determine if the currency sign
2422 2438 // is doubled or not.
2423 2439 boolean doubled = (pos + 1) < pattern.length() &&
2424 2440 pattern.charAt(pos + 1) == CURRENCY_SIGN;
2425 2441 if (doubled) { // Skip over the doubled character
2426 2442 ++pos;
2427 2443 }
2428 2444 isCurrencyFormat = true;
2429 2445 affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");
2430 2446 continue;
2431 2447 } else if (ch == QUOTE) {
2432 2448 // A quote outside quotes indicates either the
2433 2449 // opening quote or two quotes, which is a quote
2434 2450 // literal. That is, we have the first quote in 'do'
2435 2451 // or o''clock.
2436 2452 if (ch == QUOTE) {
2437 2453 if ((pos+1) < pattern.length() &&
2438 2454 pattern.charAt(pos+1) == QUOTE) {
2439 2455 ++pos;
2440 2456 affix.append("''"); // o''clock
2441 2457 } else {
2442 2458 inQuote = true; // 'do'
2443 2459 }
2444 2460 continue;
2445 2461 }
2446 2462 } else if (ch == separator) {
2447 2463 // Don't allow separators before we see digit
2448 2464 // characters of phase 1, and don't allow separators
2449 2465 // in the second pattern (j == 0).
2450 2466 if (phase == 0 || j == 0) {
2451 2467 throw new IllegalArgumentException("Unquoted special character '" +
2452 2468 ch + "' in pattern \"" + pattern + '"');
2453 2469 }
2454 2470 start = pos + 1;
2455 2471 pos = pattern.length();
2456 2472 continue;
2457 2473 }
2458 2474
2459 2475 // Next handle characters which are appended directly.
2460 2476 else if (ch == percent) {
2461 2477 if (multiplier != 1) {
2462 2478 throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
2463 2479 pattern + '"');
2464 2480 }
2465 2481 multiplier = 100;
2466 2482 affix.append("'%");
2467 2483 continue;
2468 2484 } else if (ch == perMill) {
2469 2485 if (multiplier != 1) {
2470 2486 throw new IllegalArgumentException("Too many percent/per mille characters in pattern \"" +
2471 2487 pattern + '"');
2472 2488 }
2473 2489 multiplier = 1000;
2474 2490 affix.append("'\u2030");
2475 2491 continue;
2476 2492 } else if (ch == minus) {
2477 2493 affix.append("'-");
2478 2494 continue;
2479 2495 }
2480 2496 }
2481 2497 // Note that if we are within quotes, or if this is an
2482 2498 // unquoted, non-special character, then we usually fall
2483 2499 // through to here.
2484 2500 affix.append(ch);
2485 2501 break;
2486 2502
2487 2503 case 1:
2488 2504 // Phase one must be identical in the two sub-patterns. We
2489 2505 // enforce this by doing a direct comparison. While
2490 2506 // processing the first sub-pattern, we just record its
2491 2507 // length. While processing the second, we compare
2492 2508 // characters.
2493 2509 if (j == 1) {
2494 2510 ++phaseOneLength;
2495 2511 } else {
2496 2512 if (--phaseOneLength == 0) {
2497 2513 phase = 2;
2498 2514 affix = suffix;
2499 2515 }
2500 2516 continue;
2501 2517 }
2502 2518
2503 2519 // Process the digits, decimal, and grouping characters. We
2504 2520 // record five pieces of information. We expect the digits
2505 2521 // to occur in the pattern ####0000.####, and we record the
2506 2522 // number of left digits, zero (central) digits, and right
2507 2523 // digits. The position of the last grouping character is
2508 2524 // recorded (should be somewhere within the first two blocks
2509 2525 // of characters), as is the position of the decimal point,
2510 2526 // if any (should be in the zero digits). If there is no
2511 2527 // decimal point, then there should be no right digits.
2512 2528 if (ch == digit) {
2513 2529 if (zeroDigitCount > 0) {
2514 2530 ++digitRightCount;
2515 2531 } else {
2516 2532 ++digitLeftCount;
2517 2533 }
2518 2534 if (groupingCount >= 0 && decimalPos < 0) {
2519 2535 ++groupingCount;
2520 2536 }
2521 2537 } else if (ch == zeroDigit) {
2522 2538 if (digitRightCount > 0) {
2523 2539 throw new IllegalArgumentException("Unexpected '0' in pattern \"" +
2524 2540 pattern + '"');
2525 2541 }
2526 2542 ++zeroDigitCount;
2527 2543 if (groupingCount >= 0 && decimalPos < 0) {
2528 2544 ++groupingCount;
2529 2545 }
2530 2546 } else if (ch == groupingSeparator) {
2531 2547 groupingCount = 0;
2532 2548 } else if (ch == decimalSeparator) {
2533 2549 if (decimalPos >= 0) {
2534 2550 throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +
2535 2551 pattern + '"');
2536 2552 }
2537 2553 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
2538 2554 } else if (pattern.regionMatches(pos, exponent, 0, exponent.length())){
2539 2555 if (useExponentialNotation) {
2540 2556 throw new IllegalArgumentException("Multiple exponential " +
2541 2557 "symbols in pattern \"" + pattern + '"');
2542 2558 }
2543 2559 useExponentialNotation = true;
2544 2560 minExponentDigits = 0;
2545 2561
2546 2562 // Use lookahead to parse out the exponential part
2547 2563 // of the pattern, then jump into phase 2.
2548 2564 pos = pos+exponent.length();
2549 2565 while (pos < pattern.length() &&
2550 2566 pattern.charAt(pos) == zeroDigit) {
2551 2567 ++minExponentDigits;
2552 2568 ++phaseOneLength;
2553 2569 ++pos;
2554 2570 }
2555 2571
2556 2572 if ((digitLeftCount + zeroDigitCount) < 1 ||
2557 2573 minExponentDigits < 1) {
2558 2574 throw new IllegalArgumentException("Malformed exponential " +
2559 2575 "pattern \"" + pattern + '"');
2560 2576 }
2561 2577
2562 2578 // Transition to phase 2
2563 2579 phase = 2;
2564 2580 affix = suffix;
2565 2581 --pos;
2566 2582 continue;
2567 2583 } else {
2568 2584 phase = 2;
2569 2585 affix = suffix;
2570 2586 --pos;
2571 2587 --phaseOneLength;
2572 2588 continue;
2573 2589 }
2574 2590 break;
2575 2591 }
2576 2592 }
2577 2593
2578 2594 // Handle patterns with no '0' pattern character. These patterns
2579 2595 // are legal, but must be interpreted. "##.###" -> "#0.###".
2580 2596 // ".###" -> ".0##".
2581 2597 /* We allow patterns of the form "####" to produce a zeroDigitCount
2582 2598 * of zero (got that?); although this seems like it might make it
2583 2599 * possible for format() to produce empty strings, format() checks
2584 2600 * for this condition and outputs a zero digit in this situation.
2585 2601 * Having a zeroDigitCount of zero yields a minimum integer digits
2586 2602 * of zero, which allows proper round-trip patterns. That is, we
2587 2603 * don't want "#" to become "#0" when toPattern() is called (even
2588 2604 * though that's what it really is, semantically).
2589 2605 */
2590 2606 if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
2591 2607 // Handle "###.###" and "###." and ".###"
2592 2608 int n = decimalPos;
2593 2609 if (n == 0) { // Handle ".###"
2594 2610 ++n;
2595 2611 }
2596 2612 digitRightCount = digitLeftCount - n;
2597 2613 digitLeftCount = n - 1;
2598 2614 zeroDigitCount = 1;
2599 2615 }
2600 2616
2601 2617 // Do syntax checking on the digits.
2602 2618 if ((decimalPos < 0 && digitRightCount > 0) ||
2603 2619 (decimalPos >= 0 && (decimalPos < digitLeftCount ||
2604 2620 decimalPos > (digitLeftCount + zeroDigitCount))) ||
2605 2621 groupingCount == 0 || inQuote) {
2606 2622 throw new IllegalArgumentException("Malformed pattern \"" +
2607 2623 pattern + '"');
2608 2624 }
2609 2625
2610 2626 if (j == 1) {
2611 2627 posPrefixPattern = prefix.toString();
2612 2628 posSuffixPattern = suffix.toString();
2613 2629 negPrefixPattern = posPrefixPattern; // assume these for now
2614 2630 negSuffixPattern = posSuffixPattern;
2615 2631 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
2616 2632 /* The effectiveDecimalPos is the position the decimal is at or
2617 2633 * would be at if there is no decimal. Note that if decimalPos<0,
2618 2634 * then digitTotalCount == digitLeftCount + zeroDigitCount.
2619 2635 */
2620 2636 int effectiveDecimalPos = decimalPos >= 0 ?
2621 2637 decimalPos : digitTotalCount;
2622 2638 setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);
2623 2639 setMaximumIntegerDigits(useExponentialNotation ?
2624 2640 digitLeftCount + getMinimumIntegerDigits() :
2625 2641 MAXIMUM_INTEGER_DIGITS);
2626 2642 setMaximumFractionDigits(decimalPos >= 0 ?
2627 2643 (digitTotalCount - decimalPos) : 0);
2628 2644 setMinimumFractionDigits(decimalPos >= 0 ?
2629 2645 (digitLeftCount + zeroDigitCount - decimalPos) : 0);
2630 2646 setGroupingUsed(groupingCount > 0);
2631 2647 this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
2632 2648 this.multiplier = multiplier;
2633 2649 setDecimalSeparatorAlwaysShown(decimalPos == 0 ||
2634 2650 decimalPos == digitTotalCount);
2635 2651 } else {
2636 2652 negPrefixPattern = prefix.toString();
2637 2653 negSuffixPattern = suffix.toString();
2638 2654 gotNegative = true;
2639 2655 }
2640 2656 }
2641 2657
2642 2658 if (pattern.length() == 0) {
2643 2659 posPrefixPattern = posSuffixPattern = "";
2644 2660 setMinimumIntegerDigits(0);
2645 2661 setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
2646 2662 setMinimumFractionDigits(0);
2647 2663 setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS);
2648 2664 }
2649 2665
2650 2666 // If there was no negative pattern, or if the negative pattern is
2651 2667 // identical to the positive pattern, then prepend the minus sign to
2652 2668 // the positive pattern to form the negative pattern.
2653 2669 if (!gotNegative ||
2654 2670 (negPrefixPattern.equals(posPrefixPattern)
2655 2671 && negSuffixPattern.equals(posSuffixPattern))) {
2656 2672 negSuffixPattern = posSuffixPattern;
2657 2673 negPrefixPattern = "'-" + posPrefixPattern;
2658 2674 }
2659 2675
2660 2676 expandAffixes();
↓ open down ↓ |
709 lines elided |
↑ open up ↑ |
2661 2677 }
2662 2678
2663 2679 /**
2664 2680 * Sets the maximum number of digits allowed in the integer portion of a
2665 2681 * number.
2666 2682 * For formatting numbers other than <code>BigInteger</code> and
2667 2683 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
2668 2684 * 309 is used. Negative input values are replaced with 0.
2669 2685 * @see NumberFormat#setMaximumIntegerDigits
2670 2686 */
2687 + @Override
2671 2688 public void setMaximumIntegerDigits(int newValue) {
2672 2689 maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
2673 2690 super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
2674 2691 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
2675 2692 if (minimumIntegerDigits > maximumIntegerDigits) {
2676 2693 minimumIntegerDigits = maximumIntegerDigits;
2677 2694 super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
2678 2695 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
2679 2696 }
2680 2697 }
2681 2698
2682 2699 /**
2683 2700 * Sets the minimum number of digits allowed in the integer portion of a
2684 2701 * number.
2685 2702 * For formatting numbers other than <code>BigInteger</code> and
2686 2703 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
2687 2704 * 309 is used. Negative input values are replaced with 0.
2688 2705 * @see NumberFormat#setMinimumIntegerDigits
2689 2706 */
2707 + @Override
2690 2708 public void setMinimumIntegerDigits(int newValue) {
2691 2709 minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
2692 2710 super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
2693 2711 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
2694 2712 if (minimumIntegerDigits > maximumIntegerDigits) {
2695 2713 maximumIntegerDigits = minimumIntegerDigits;
2696 2714 super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
2697 2715 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
2698 2716 }
2699 2717 }
2700 2718
2701 2719 /**
2702 2720 * Sets the maximum number of digits allowed in the fraction portion of a
2703 2721 * number.
2704 2722 * For formatting numbers other than <code>BigInteger</code> and
2705 2723 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
2706 2724 * 340 is used. Negative input values are replaced with 0.
2707 2725 * @see NumberFormat#setMaximumFractionDigits
2708 2726 */
2727 + @Override
2709 2728 public void setMaximumFractionDigits(int newValue) {
2710 2729 maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
2711 2730 super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
2712 2731 DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
2713 2732 if (minimumFractionDigits > maximumFractionDigits) {
2714 2733 minimumFractionDigits = maximumFractionDigits;
2715 2734 super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
2716 2735 DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
2717 2736 }
2718 2737 }
2719 2738
2720 2739 /**
2721 2740 * Sets the minimum number of digits allowed in the fraction portion of a
2722 2741 * number.
2723 2742 * For formatting numbers other than <code>BigInteger</code> and
2724 2743 * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
2725 2744 * 340 is used. Negative input values are replaced with 0.
2726 2745 * @see NumberFormat#setMinimumFractionDigits
2727 2746 */
2747 + @Override
2728 2748 public void setMinimumFractionDigits(int newValue) {
2729 2749 minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
2730 2750 super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
2731 2751 DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
2732 2752 if (minimumFractionDigits > maximumFractionDigits) {
2733 2753 maximumFractionDigits = minimumFractionDigits;
2734 2754 super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
2735 2755 DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
2736 2756 }
2737 2757 }
2738 2758
2739 2759 /**
2740 2760 * Gets the maximum number of digits allowed in the integer portion of a
2741 2761 * number.
2742 2762 * For formatting numbers other than <code>BigInteger</code> and
2743 2763 * <code>BigDecimal</code> objects, the lower of the return value and
2744 2764 * 309 is used.
2745 2765 * @see #setMaximumIntegerDigits
2746 2766 */
2767 + @Override
2747 2768 public int getMaximumIntegerDigits() {
2748 2769 return maximumIntegerDigits;
2749 2770 }
2750 2771
2751 2772 /**
2752 2773 * Gets the minimum number of digits allowed in the integer portion of a
2753 2774 * number.
2754 2775 * For formatting numbers other than <code>BigInteger</code> and
2755 2776 * <code>BigDecimal</code> objects, the lower of the return value and
2756 2777 * 309 is used.
2757 2778 * @see #setMinimumIntegerDigits
2758 2779 */
2780 + @Override
2759 2781 public int getMinimumIntegerDigits() {
2760 2782 return minimumIntegerDigits;
2761 2783 }
2762 2784
2763 2785 /**
2764 2786 * Gets the maximum number of digits allowed in the fraction portion of a
2765 2787 * number.
2766 2788 * For formatting numbers other than <code>BigInteger</code> and
2767 2789 * <code>BigDecimal</code> objects, the lower of the return value and
2768 2790 * 340 is used.
2769 2791 * @see #setMaximumFractionDigits
2770 2792 */
2793 + @Override
2771 2794 public int getMaximumFractionDigits() {
2772 2795 return maximumFractionDigits;
2773 2796 }
2774 2797
2775 2798 /**
2776 2799 * Gets the minimum number of digits allowed in the fraction portion of a
2777 2800 * number.
2778 2801 * For formatting numbers other than <code>BigInteger</code> and
2779 2802 * <code>BigDecimal</code> objects, the lower of the return value and
2780 2803 * 340 is used.
2781 2804 * @see #setMinimumFractionDigits
2782 2805 */
2806 + @Override
2783 2807 public int getMinimumFractionDigits() {
2784 2808 return minimumFractionDigits;
2785 2809 }
2786 2810
2787 2811 /**
2788 2812 * Gets the currency used by this decimal format when formatting
2789 2813 * currency values.
2790 2814 * The currency is obtained by calling
2791 2815 * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
2792 2816 * on this number format's symbols.
2793 2817 *
2794 2818 * @return the currency used by this decimal format, or <code>null</code>
2795 2819 * @since 1.4
2796 2820 */
2821 + @Override
2797 2822 public Currency getCurrency() {
2798 2823 return symbols.getCurrency();
2799 2824 }
2800 2825
2801 2826 /**
2802 2827 * Sets the currency used by this number format when formatting
2803 2828 * currency values. This does not update the minimum or maximum
2804 2829 * number of fraction digits used by the number format.
2805 2830 * The currency is set by calling
2806 2831 * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
2807 2832 * on this number format's symbols.
2808 2833 *
2809 2834 * @param currency the new currency to be used by this decimal format
2810 2835 * @exception NullPointerException if <code>currency</code> is null
2811 2836 * @since 1.4
2812 2837 */
2838 + @Override
2813 2839 public void setCurrency(Currency currency) {
2814 2840 if (currency != symbols.getCurrency()) {
2815 2841 symbols.setCurrency(currency);
2816 2842 if (isCurrencyFormat) {
2817 2843 expandAffixes();
2818 2844 }
2819 2845 }
2820 2846 }
2821 2847
2822 2848 /**
2823 2849 * Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
2824 2850 *
2825 2851 * @return The <code>RoundingMode</code> used for this DecimalFormat.
2826 2852 * @see #setRoundingMode(RoundingMode)
2827 2853 * @since 1.6
2828 2854 */
2855 + @Override
2829 2856 public RoundingMode getRoundingMode() {
2830 2857 return roundingMode;
2831 2858 }
2832 2859
2833 2860 /**
2834 2861 * Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
2835 2862 *
2836 2863 * @param roundingMode The <code>RoundingMode</code> to be used
2837 2864 * @see #getRoundingMode()
2838 2865 * @exception NullPointerException if <code>roundingMode</code> is null.
2839 2866 * @since 1.6
2840 2867 */
2868 + @Override
2841 2869 public void setRoundingMode(RoundingMode roundingMode) {
2842 2870 if (roundingMode == null) {
2843 2871 throw new NullPointerException();
2844 2872 }
2845 2873
2846 2874 this.roundingMode = roundingMode;
2847 2875 digitList.setRoundingMode(roundingMode);
2848 2876 }
2849 2877
2850 2878 /**
2851 - * Adjusts the minimum and maximum fraction digits to values that
2852 - * are reasonable for the currency's default fraction digits.
2853 - */
2854 - void adjustForCurrencyDefaultFractionDigits() {
2855 - Currency currency = symbols.getCurrency();
2856 - if (currency == null) {
2857 - try {
2858 - currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
2859 - } catch (IllegalArgumentException e) {
2860 - }
2861 - }
2862 - if (currency != null) {
2863 - int digits = currency.getDefaultFractionDigits();
2864 - if (digits != -1) {
2865 - int oldMinDigits = getMinimumFractionDigits();
2866 - // Common patterns are "#.##", "#.00", "#".
2867 - // Try to adjust all of them in a reasonable way.
2868 - if (oldMinDigits == getMaximumFractionDigits()) {
2869 - setMinimumFractionDigits(digits);
2870 - setMaximumFractionDigits(digits);
2871 - } else {
2872 - setMinimumFractionDigits(Math.min(digits, oldMinDigits));
2873 - setMaximumFractionDigits(digits);
2874 - }
2875 - }
2876 - }
2877 - }
2878 -
2879 - /**
2880 2879 * Reads the default serializable fields from the stream and performs
2881 2880 * validations and adjustments for older serialized versions. The
2882 2881 * validations and adjustments are:
2883 2882 * <ol>
2884 2883 * <li>
2885 2884 * Verify that the superclass's digit count fields correctly reflect
2886 2885 * the limits imposed on formatting numbers other than
2887 2886 * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
2888 2887 * limits are stored in the superclass for serialization compatibility
2889 2888 * with older versions, while the limits for <code>BigInteger</code> and
2890 2889 * <code>BigDecimal</code> objects are kept in this class.
2891 2890 * If, in the superclass, the minimum or maximum integer digit count is
2892 2891 * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
2893 2892 * maximum fraction digit count is larger than
2894 2893 * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
2895 2894 * and this method throws an <code>InvalidObjectException</code>.
2896 2895 * <li>
2897 2896 * If <code>serialVersionOnStream</code> is less than 4, initialize
2898 2897 * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
2899 2898 * RoundingMode.HALF_EVEN}. This field is new with version 4.
2900 2899 * <li>
2901 2900 * If <code>serialVersionOnStream</code> is less than 3, then call
2902 2901 * the setters for the minimum and maximum integer and fraction digits with
2903 2902 * the values of the corresponding superclass getters to initialize the
2904 2903 * fields in this class. The fields in this class are new with version 3.
2905 2904 * <li>
2906 2905 * If <code>serialVersionOnStream</code> is less than 1, indicating that
2907 2906 * the stream was written by JDK 1.1, initialize
2908 2907 * <code>useExponentialNotation</code>
2909 2908 * to false, since it was not present in JDK 1.1.
2910 2909 * <li>
2911 2910 * Set <code>serialVersionOnStream</code> to the maximum allowed value so
2912 2911 * that default serialization will work properly if this object is streamed
2913 2912 * out again.
2914 2913 * </ol>
2915 2914 *
2916 2915 * <p>Stream versions older than 2 will not have the affix pattern variables
2917 2916 * <code>posPrefixPattern</code> etc. As a result, they will be initialized
2918 2917 * to <code>null</code>, which means the affix strings will be taken as
2919 2918 * literal values. This is exactly what we want, since that corresponds to
2920 2919 * the pre-version-2 behavior.
2921 2920 */
2922 2921 private void readObject(ObjectInputStream stream)
2923 2922 throws IOException, ClassNotFoundException
2924 2923 {
2925 2924 stream.defaultReadObject();
2926 2925 digitList = new DigitList();
2927 2926
2928 2927 if (serialVersionOnStream < 4) {
2929 2928 setRoundingMode(RoundingMode.HALF_EVEN);
2930 2929 }
2931 2930 // We only need to check the maximum counts because NumberFormat
2932 2931 // .readObject has already ensured that the maximum is greater than the
2933 2932 // minimum count.
2934 2933 if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
2935 2934 super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
2936 2935 throw new InvalidObjectException("Digit count out of range");
2937 2936 }
2938 2937 if (serialVersionOnStream < 3) {
2939 2938 setMaximumIntegerDigits(super.getMaximumIntegerDigits());
2940 2939 setMinimumIntegerDigits(super.getMinimumIntegerDigits());
2941 2940 setMaximumFractionDigits(super.getMaximumFractionDigits());
2942 2941 setMinimumFractionDigits(super.getMinimumFractionDigits());
2943 2942 }
2944 2943 if (serialVersionOnStream < 1) {
2945 2944 // Didn't have exponential fields
2946 2945 useExponentialNotation = false;
2947 2946 }
2948 2947 serialVersionOnStream = currentSerialVersion;
2949 2948 }
2950 2949
2951 2950 //----------------------------------------------------------------------
2952 2951 // INSTANCE VARIABLES
2953 2952 //----------------------------------------------------------------------
2954 2953
2955 2954 private transient DigitList digitList = new DigitList();
2956 2955
2957 2956 /**
2958 2957 * The symbol used as a prefix when formatting positive numbers, e.g. "+".
2959 2958 *
2960 2959 * @serial
2961 2960 * @see #getPositivePrefix
2962 2961 */
2963 2962 private String positivePrefix = "";
2964 2963
2965 2964 /**
2966 2965 * The symbol used as a suffix when formatting positive numbers.
2967 2966 * This is often an empty string.
2968 2967 *
2969 2968 * @serial
2970 2969 * @see #getPositiveSuffix
2971 2970 */
2972 2971 private String positiveSuffix = "";
2973 2972
2974 2973 /**
2975 2974 * The symbol used as a prefix when formatting negative numbers, e.g. "-".
2976 2975 *
2977 2976 * @serial
2978 2977 * @see #getNegativePrefix
2979 2978 */
2980 2979 private String negativePrefix = "-";
2981 2980
2982 2981 /**
2983 2982 * The symbol used as a suffix when formatting negative numbers.
2984 2983 * This is often an empty string.
2985 2984 *
2986 2985 * @serial
2987 2986 * @see #getNegativeSuffix
2988 2987 */
2989 2988 private String negativeSuffix = "";
2990 2989
2991 2990 /**
2992 2991 * The prefix pattern for non-negative numbers. This variable corresponds
2993 2992 * to <code>positivePrefix</code>.
2994 2993 *
2995 2994 * <p>This pattern is expanded by the method <code>expandAffix()</code> to
2996 2995 * <code>positivePrefix</code> to update the latter to reflect changes in
2997 2996 * <code>symbols</code>. If this variable is <code>null</code> then
2998 2997 * <code>positivePrefix</code> is taken as a literal value that does not
2999 2998 * change when <code>symbols</code> changes. This variable is always
3000 2999 * <code>null</code> for <code>DecimalFormat</code> objects older than
3001 3000 * stream version 2 restored from stream.
3002 3001 *
3003 3002 * @serial
3004 3003 * @since 1.3
3005 3004 */
3006 3005 private String posPrefixPattern;
3007 3006
3008 3007 /**
3009 3008 * The suffix pattern for non-negative numbers. This variable corresponds
3010 3009 * to <code>positiveSuffix</code>. This variable is analogous to
3011 3010 * <code>posPrefixPattern</code>; see that variable for further
3012 3011 * documentation.
3013 3012 *
3014 3013 * @serial
3015 3014 * @since 1.3
3016 3015 */
3017 3016 private String posSuffixPattern;
3018 3017
3019 3018 /**
3020 3019 * The prefix pattern for negative numbers. This variable corresponds
3021 3020 * to <code>negativePrefix</code>. This variable is analogous to
3022 3021 * <code>posPrefixPattern</code>; see that variable for further
3023 3022 * documentation.
3024 3023 *
3025 3024 * @serial
3026 3025 * @since 1.3
3027 3026 */
3028 3027 private String negPrefixPattern;
3029 3028
3030 3029 /**
3031 3030 * The suffix pattern for negative numbers. This variable corresponds
3032 3031 * to <code>negativeSuffix</code>. This variable is analogous to
3033 3032 * <code>posPrefixPattern</code>; see that variable for further
3034 3033 * documentation.
3035 3034 *
3036 3035 * @serial
3037 3036 * @since 1.3
3038 3037 */
3039 3038 private String negSuffixPattern;
3040 3039
3041 3040 /**
3042 3041 * The multiplier for use in percent, per mille, etc.
3043 3042 *
3044 3043 * @serial
3045 3044 * @see #getMultiplier
3046 3045 */
3047 3046 private int multiplier = 1;
3048 3047
3049 3048 /**
3050 3049 * The number of digits between grouping separators in the integer
3051 3050 * portion of a number. Must be greater than 0 if
3052 3051 * <code>NumberFormat.groupingUsed</code> is true.
3053 3052 *
3054 3053 * @serial
3055 3054 * @see #getGroupingSize
3056 3055 * @see java.text.NumberFormat#isGroupingUsed
3057 3056 */
3058 3057 private byte groupingSize = 3; // invariant, > 0 if useThousands
3059 3058
3060 3059 /**
3061 3060 * If true, forces the decimal separator to always appear in a formatted
3062 3061 * number, even if the fractional part of the number is zero.
3063 3062 *
3064 3063 * @serial
3065 3064 * @see #isDecimalSeparatorAlwaysShown
3066 3065 */
3067 3066 private boolean decimalSeparatorAlwaysShown = false;
3068 3067
3069 3068 /**
3070 3069 * If true, parse returns BigDecimal wherever possible.
3071 3070 *
3072 3071 * @serial
3073 3072 * @see #isParseBigDecimal
3074 3073 * @since 1.5
3075 3074 */
3076 3075 private boolean parseBigDecimal = false;
3077 3076
3078 3077
3079 3078 /**
3080 3079 * True if this object represents a currency format. This determines
3081 3080 * whether the monetary decimal separator is used instead of the normal one.
3082 3081 */
3083 3082 private transient boolean isCurrencyFormat = false;
3084 3083
3085 3084 /**
3086 3085 * The <code>DecimalFormatSymbols</code> object used by this format.
3087 3086 * It contains the symbols used to format numbers, e.g. the grouping separator,
3088 3087 * decimal separator, and so on.
3089 3088 *
3090 3089 * @serial
3091 3090 * @see #setDecimalFormatSymbols
3092 3091 * @see java.text.DecimalFormatSymbols
3093 3092 */
3094 3093 private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
3095 3094
3096 3095 /**
3097 3096 * True to force the use of exponential (i.e. scientific) notation when formatting
3098 3097 * numbers.
3099 3098 *
3100 3099 * @serial
3101 3100 * @since 1.2
3102 3101 */
3103 3102 private boolean useExponentialNotation; // Newly persistent in the Java 2 platform v.1.2
3104 3103
3105 3104 /**
3106 3105 * FieldPositions describing the positive prefix String. This is
3107 3106 * lazily created. Use <code>getPositivePrefixFieldPositions</code>
3108 3107 * when needed.
3109 3108 */
3110 3109 private transient FieldPosition[] positivePrefixFieldPositions;
3111 3110
3112 3111 /**
3113 3112 * FieldPositions describing the positive suffix String. This is
3114 3113 * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
3115 3114 * when needed.
3116 3115 */
3117 3116 private transient FieldPosition[] positiveSuffixFieldPositions;
3118 3117
3119 3118 /**
3120 3119 * FieldPositions describing the negative prefix String. This is
3121 3120 * lazily created. Use <code>getNegativePrefixFieldPositions</code>
3122 3121 * when needed.
3123 3122 */
3124 3123 private transient FieldPosition[] negativePrefixFieldPositions;
3125 3124
3126 3125 /**
3127 3126 * FieldPositions describing the negative suffix String. This is
3128 3127 * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
3129 3128 * when needed.
3130 3129 */
3131 3130 private transient FieldPosition[] negativeSuffixFieldPositions;
3132 3131
3133 3132 /**
3134 3133 * The minimum number of digits used to display the exponent when a number is
3135 3134 * formatted in exponential notation. This field is ignored if
3136 3135 * <code>useExponentialNotation</code> is not true.
3137 3136 *
3138 3137 * @serial
3139 3138 * @since 1.2
3140 3139 */
3141 3140 private byte minExponentDigits; // Newly persistent in the Java 2 platform v.1.2
3142 3141
3143 3142 /**
3144 3143 * The maximum number of digits allowed in the integer portion of a
3145 3144 * <code>BigInteger</code> or <code>BigDecimal</code> number.
3146 3145 * <code>maximumIntegerDigits</code> must be greater than or equal to
3147 3146 * <code>minimumIntegerDigits</code>.
3148 3147 *
3149 3148 * @serial
3150 3149 * @see #getMaximumIntegerDigits
3151 3150 * @since 1.5
3152 3151 */
3153 3152 private int maximumIntegerDigits = super.getMaximumIntegerDigits();
3154 3153
3155 3154 /**
3156 3155 * The minimum number of digits allowed in the integer portion of a
3157 3156 * <code>BigInteger</code> or <code>BigDecimal</code> number.
3158 3157 * <code>minimumIntegerDigits</code> must be less than or equal to
3159 3158 * <code>maximumIntegerDigits</code>.
3160 3159 *
3161 3160 * @serial
3162 3161 * @see #getMinimumIntegerDigits
3163 3162 * @since 1.5
3164 3163 */
3165 3164 private int minimumIntegerDigits = super.getMinimumIntegerDigits();
3166 3165
3167 3166 /**
3168 3167 * The maximum number of digits allowed in the fractional portion of a
3169 3168 * <code>BigInteger</code> or <code>BigDecimal</code> number.
3170 3169 * <code>maximumFractionDigits</code> must be greater than or equal to
3171 3170 * <code>minimumFractionDigits</code>.
3172 3171 *
3173 3172 * @serial
3174 3173 * @see #getMaximumFractionDigits
3175 3174 * @since 1.5
3176 3175 */
3177 3176 private int maximumFractionDigits = super.getMaximumFractionDigits();
3178 3177
3179 3178 /**
3180 3179 * The minimum number of digits allowed in the fractional portion of a
3181 3180 * <code>BigInteger</code> or <code>BigDecimal</code> number.
3182 3181 * <code>minimumFractionDigits</code> must be less than or equal to
3183 3182 * <code>maximumFractionDigits</code>.
3184 3183 *
3185 3184 * @serial
3186 3185 * @see #getMinimumFractionDigits
3187 3186 * @since 1.5
3188 3187 */
3189 3188 private int minimumFractionDigits = super.getMinimumFractionDigits();
3190 3189
3191 3190 /**
3192 3191 * The {@link java.math.RoundingMode} used in this DecimalFormat.
3193 3192 *
3194 3193 * @serial
3195 3194 * @since 1.6
3196 3195 */
3197 3196 private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
3198 3197
3199 3198 //----------------------------------------------------------------------
3200 3199
3201 3200 static final int currentSerialVersion = 4;
3202 3201
3203 3202 /**
3204 3203 * The internal serial version which says which version was written.
3205 3204 * Possible values are:
3206 3205 * <ul>
3207 3206 * <li><b>0</b> (default): versions before the Java 2 platform v1.2
3208 3207 * <li><b>1</b>: version for 1.2, which includes the two new fields
3209 3208 * <code>useExponentialNotation</code> and
3210 3209 * <code>minExponentDigits</code>.
3211 3210 * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
3212 3211 * <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
3213 3212 * <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
3214 3213 * <li><b>3</b>: version for 1.5 and later, which adds five new fields:
3215 3214 * <code>maximumIntegerDigits</code>,
3216 3215 * <code>minimumIntegerDigits</code>,
3217 3216 * <code>maximumFractionDigits</code>,
3218 3217 * <code>minimumFractionDigits</code>, and
3219 3218 * <code>parseBigDecimal</code>.
3220 3219 * <li><b>4</b>: version for 1.6 and later, which adds one new field:
3221 3220 * <code>roundingMode</code>.
3222 3221 * </ul>
3223 3222 * @since 1.2
3224 3223 * @serial
3225 3224 */
3226 3225 private int serialVersionOnStream = currentSerialVersion;
3227 3226
3228 3227 //----------------------------------------------------------------------
3229 3228 // CONSTANTS
3230 3229 //----------------------------------------------------------------------
3231 3230
3232 3231 // Constants for characters used in programmatic (unlocalized) patterns.
3233 3232 private static final char PATTERN_ZERO_DIGIT = '0';
3234 3233 private static final char PATTERN_GROUPING_SEPARATOR = ',';
3235 3234 private static final char PATTERN_DECIMAL_SEPARATOR = '.';
3236 3235 private static final char PATTERN_PER_MILLE = '\u2030';
3237 3236 private static final char PATTERN_PERCENT = '%';
3238 3237 private static final char PATTERN_DIGIT = '#';
3239 3238 private static final char PATTERN_SEPARATOR = ';';
3240 3239 private static final String PATTERN_EXPONENT = "E";
3241 3240 private static final char PATTERN_MINUS = '-';
3242 3241
3243 3242 /**
3244 3243 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
3245 3244 * is used in patterns and substituted with either the currency symbol,
3246 3245 * or if it is doubled, with the international currency symbol. If the
3247 3246 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
3248 3247 * replaced with the monetary decimal separator.
3249 3248 *
3250 3249 * The CURRENCY_SIGN is not localized.
3251 3250 */
3252 3251 private static final char CURRENCY_SIGN = '\u00A4';
3253 3252
3254 3253 private static final char QUOTE = '\'';
3255 3254
3256 3255 private static FieldPosition[] EmptyFieldPositionArray = new FieldPosition[0];
3257 3256
3258 3257 // Upper limit on integer and fraction digits for a Java double
3259 3258 static final int DOUBLE_INTEGER_DIGITS = 309;
3260 3259 static final int DOUBLE_FRACTION_DIGITS = 340;
3261 3260
3262 3261 // Upper limit on integer and fraction digits for BigDecimal and BigInteger
↓ open down ↓ |
373 lines elided |
↑ open up ↑ |
3263 3262 static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE;
3264 3263 static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE;
3265 3264
3266 3265 // Proclaim JDK 1.1 serial compatibility.
3267 3266 static final long serialVersionUID = 864413376551465018L;
3268 3267
3269 3268 /**
3270 3269 * Cache to hold the NumberPattern of a Locale.
3271 3270 */
3272 3271 private static final ConcurrentMap<Locale, String> cachedLocaleData
3273 - = new ConcurrentHashMap<Locale, String>(3);
3272 + = new ConcurrentHashMap<>(3);
3274 3273 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX