2 *******************************************************************************
\r
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.text;
\r
9 import java.io.IOException;
\r
10 import java.io.ObjectInputStream;
\r
11 import java.io.ObjectOutputStream;
\r
12 import java.math.BigInteger;
\r
13 import java.text.AttributedCharacterIterator;
\r
14 import java.text.AttributedString;
\r
15 import java.text.ChoiceFormat;
\r
16 import java.text.FieldPosition;
\r
17 import java.text.Format;
\r
18 import java.text.ParsePosition;
\r
19 import java.util.ArrayList;
\r
20 import java.util.HashSet;
\r
21 import java.util.Iterator;
\r
22 import java.util.Set;
\r
24 import com.ibm.icu.impl.ICUConfig;
\r
25 import com.ibm.icu.impl.UCharacterProperty;
\r
26 import com.ibm.icu.impl.Utility;
\r
27 import com.ibm.icu.lang.UCharacter;
\r
28 import com.ibm.icu.math.BigDecimal;
\r
29 import com.ibm.icu.math.MathContext;
\r
30 import com.ibm.icu.util.Currency;
\r
31 import com.ibm.icu.util.CurrencyAmount;
\r
32 import com.ibm.icu.util.ULocale;
\r
35 * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
\r
37 * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats
\r
38 * decimal numbers. It has a variety of features designed to make it possible to parse and
\r
39 * format numbers in any locale, including support for Western, Arabic, or Indic digits.
\r
40 * It also supports different flavors of numbers, including integers ("123"), fixed-point
\r
41 * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency
\r
42 * amounts ("$123.00", "USD123.00", "123.00 US dollars"). All of these flavors can be
\r
45 * <p>To obtain a {@link NumberFormat} for a specific locale (including the default
\r
46 * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link
\r
47 * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors
\r
48 * directly, unless you know what you are doing, since the {@link NumberFormat} factory
\r
49 * methods may return subclasses other than <code>DecimalFormat</code>. If you need to
\r
50 * customize the format object, do something like this:
\r
53 * NumberFormat f = NumberFormat.getInstance(loc);
\r
54 * if (f instanceof DecimalFormat) {
\r
55 * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
\r
56 * }</pre></blockquote>
\r
58 * <p><strong>Example Usage</strong>
\r
60 * Print out a number using the localized number, currency, and percent
\r
61 * format for each locale.
\r
64 * Locale[] locales = NumberFormat.getAvailableLocales();
\r
65 * double myNumber = -1234.56;
\r
66 * NumberFormat format;
\r
67 * for (int j=0; j<3; ++j) {
\r
68 * System.out.println("FORMAT");
\r
69 * for (int i = 0; i < locales.length; ++i) {
\r
70 * if (locales[i].getCountry().length() == 0) {
\r
71 * // Skip language-only locales
\r
74 * System.out.print(locales[i].getDisplayName());
\r
77 * format = NumberFormat.getInstance(locales[i]); break;
\r
79 * format = NumberFormat.getCurrencyInstance(locales[i]); break;
\r
81 * format = NumberFormat.getPercentInstance(locales[i]); break;
\r
84 * // Assume format is a DecimalFormat
\r
85 * System.out.print(": " + ((DecimalFormat) format).toPattern()
\r
86 * + " -> " + form.format(myNumber));
\r
87 * } catch (Exception e) {}
\r
89 * System.out.println(" -> " + format.parse(form.format(myNumber)));
\r
90 * } catch (ParseException e) {}
\r
92 * }</pre></blockquote>
\r
94 * <p>Another example use getInstance(style).<br/>
\r
95 * Print out a number using the localized number, currency, percent,
\r
96 * scientific, integer, iso currency, and plural currency format for each locale.
\r
99 * ULocale locale = new ULocale("en_US");
\r
100 * double myNumber = 1234.56;
\r
101 * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
\r
102 * NumberFormat format = NumberFormat.getInstance(locale, j);
\r
104 * // Assume format is a DecimalFormat
\r
105 * System.out.print(": " + ((DecimalFormat) format).toPattern()
\r
106 * + " -> " + form.format(myNumber));
\r
107 * } catch (Exception e) {}
\r
109 * System.out.println(" -> " + format.parse(form.format(myNumber)));
\r
110 * } catch (ParseException e) {}
\r
111 * }</pre></blockquote>
\r
113 * <h4>Patterns</h4>
\r
115 * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
\r
116 * <em>symbols</em>. The pattern may be set directly using {@link #applyPattern}, or
\r
117 * indirectly using other API methods which manipulate aspects of the pattern, such as the
\r
118 * minimum number of integer digits. The symbols are stored in a {@link
\r
119 * DecimalFormatSymbols} object. When using the {@link NumberFormat} factory methods, the
\r
120 * pattern and symbols are read from ICU's locale data.
\r
122 * <h4>Special Pattern Characters</h4>
\r
124 * <p>Many characters in a pattern are taken literally; they are matched during parsing
\r
125 * and output unchanged during formatting. Special characters, on the other hand, stand
\r
126 * for other characters, strings, or classes of characters. For example, the '#'
\r
127 * character is replaced by a localized digit. Often the replacement character is the
\r
128 * same as the pattern character; in the U.S. locale, the ',' grouping character is
\r
129 * replaced by ','. However, the replacement is still happening, and if the symbols are
\r
130 * modified, the grouping character changes. Some special characters affect the behavior
\r
131 * of the formatter by their presence; for example, if the percent character is seen, then
\r
132 * the value is multiplied by 100 before being displayed.
\r
134 * <p>To insert a special character in a pattern as a literal, that is, without any
\r
135 * special meaning, the character must be quoted. There are some exceptions to this which
\r
138 * <p>The characters listed here are used in non-localized patterns. Localized patterns
\r
139 * use the corresponding characters taken from this formatter's {@link
\r
140 * DecimalFormatSymbols} object instead, and these characters lose their special status.
\r
141 * Two exceptions are the currency sign and quote, which are not localized.
\r
144 * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
\r
145 * location, localized, and meaning.">
\r
146 * <tr bgcolor="#ccccff">
\r
147 * <th align=left>Symbol
\r
148 * <th align=left>Location
\r
149 * <th align=left>Localized?
\r
150 * <th align=left>Meaning
\r
152 * <td><code>0</code>
\r
156 * <tr valign=top bgcolor="#eeeeff">
\r
157 * <td><code>1-9</code>
\r
160 * <td>'1' through '9' indicate rounding.
\r
162 * <td><code>@</code>
\r
165 * <td>Significant digit
\r
166 * <tr valign=top bgcolor="#eeeeff">
\r
167 * <td><code>#</code>
\r
170 * <td>Digit, zero shows as absent
\r
172 * <td><code>.</code>
\r
175 * <td>Decimal separator or monetary decimal separator
\r
176 * <tr valign=top bgcolor="#eeeeff">
\r
177 * <td><code>-</code>
\r
182 * <td><code>,</code>
\r
185 * <td>Grouping separator
\r
186 * <tr valign=top bgcolor="#eeeeff">
\r
187 * <td><code>E</code>
\r
190 * <td>Separates mantissa and exponent in scientific notation.
\r
191 * <em>Need not be quoted in prefix or suffix.</em>
\r
193 * <td><code>+</code>
\r
196 * <td>Prefix positive exponents with localized plus sign.
\r
197 * <em>Need not be quoted in prefix or suffix.</em>
\r
198 * <tr valign=top bgcolor="#eeeeff">
\r
199 * <td><code>;</code>
\r
200 * <td>Subpattern boundary
\r
202 * <td>Separates positive and negative subpatterns
\r
204 * <td><code>%</code>
\r
205 * <td>Prefix or suffix
\r
207 * <td>Multiply by 100 and show as percentage
\r
208 * <tr valign=top bgcolor="#eeeeff">
\r
209 * <td><code>\u2030</code>
\r
210 * <td>Prefix or suffix
\r
212 * <td>Multiply by 1000 and show as per mille
\r
214 * <td><code>¤</code> (<code>\u00A4</code>)
\r
215 * <td>Prefix or suffix
\r
217 * <td>Currency sign, replaced by currency symbol. If
\r
218 * doubled, replaced by international currency symbol.
\r
219 * If tripled, replaced by currency plural names, for example,
\r
220 * "US dollar" or "US dollars" for America.
\r
221 * If present in a pattern, the monetary decimal separator
\r
222 * is used instead of the decimal separator.
\r
223 * <tr valign=top bgcolor="#eeeeff">
\r
224 * <td><code>'</code>
\r
225 * <td>Prefix or suffix
\r
227 * <td>Used to quote special characters in a prefix or suffix,
\r
228 * for example, <code>"'#'#"</code> formats 123 to
\r
229 * <code>"#123"</code>. To create a single quote
\r
230 * itself, use two in a row: <code>"# o''clock"</code>.
\r
232 * <td><code>*</code>
\r
233 * <td>Prefix or suffix boundary
\r
235 * <td>Pad escape, precedes pad character
\r
239 * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for
\r
240 * example, "#,##0.00;(#,##0.00)". Each subpattern has a prefix, a numeric part, and a
\r
241 * suffix. If there is no explicit negative subpattern, the negative subpattern is the
\r
242 * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is
\r
243 * equivalent to "0.00;-0.00". If there is an explicit negative subpattern, it serves
\r
244 * only to specify the negative prefix and suffix; the number of digits, minimal digits,
\r
245 * and other characteristics are ignored in the negative subpattern. That means that
\r
246 * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
\r
248 * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands
\r
249 * separators, decimal separators, etc. may be set to arbitrary values, and they will
\r
250 * appear properly during formatting. However, care must be taken that the symbols and
\r
251 * strings do not conflict, or parsing will be unreliable. For example, either the
\r
252 * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to
\r
253 * be able to distinguish positive from negative values. Another example is that the
\r
254 * decimal separator and thousands separator should be distinct characters, or parsing
\r
255 * will be impossible.
\r
257 * <p>The <em>grouping separator</em> is a character that separates clusters of integer
\r
258 * digits to make large numbers more legible. It commonly used for thousands, but in some
\r
259 * locales it separates ten-thousands. The <em>grouping size</em> is the number of digits
\r
260 * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000
\r
261 * 0000". There are actually two different grouping sizes: One used for the least
\r
262 * significant integer digits, the <em>primary grouping size</em>, and one used for all
\r
263 * others, the <em>secondary grouping size</em>. In most locales these are the same, but
\r
264 * sometimes they are different. For example, if the primary grouping interval is 3, and
\r
265 * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number
\r
266 * 123456789 is formatted as "12,34,56,789". If a pattern contains multiple grouping
\r
267 * separators, the interval between the last one and the end of the integer defines the
\r
268 * primary grouping size, and the interval between the last two defines the secondary
\r
269 * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==
\r
272 * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
\r
273 * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message
\r
274 * that describes the problem.
\r
276 * <h4>Pattern BNF</h4>
\r
279 * pattern := subpattern (';' subpattern)?
\r
280 * subpattern := prefix? number exponent? suffix?
\r
281 * number := (integer ('.' fraction)?) | sigDigits
\r
282 * prefix := '\u0000'..'\uFFFD' - specialCharacters
\r
283 * suffix := '\u0000'..'\uFFFD' - specialCharacters
\r
284 * integer := '#'* '0'* '0'
\r
285 * fraction := '0'* '#'*
\r
286 * sigDigits := '#'* '@' '@'* '#'*
\r
287 * exponent := 'E' '+'? '0'* '0'
\r
288 * padSpec := '*' padChar
\r
289 * padChar := '\u0000'..'\uFFFD' - quote
\r
292 * X* 0 or more instances of X
\r
293 * X? 0 or 1 instances of X
\r
294 * X|Y either X or Y
\r
295 * C..D any character from C up to D, inclusive
\r
296 * S-T characters in S, except those in T
\r
298 * The first subpattern is for positive numbers. The second (optional)
\r
299 * subpattern is for negative numbers.
\r
301 * <p>Not indicated in the BNF syntax above:
\r
305 * <li>The grouping separator ',' can occur inside the integer and sigDigits
\r
306 * elements, between any two pattern characters of that element, as long as the integer or
\r
307 * sigDigits element is not followed by the exponent element.
\r
309 * <li>Two grouping intervals are recognized: That between the decimal point and the first
\r
310 * grouping symbol, and that between the first and second grouping symbols. These
\r
311 * intervals are identical in most locales, but in some locales they differ. For example,
\r
312 * the pattern "#,##,###" formats the number 123456789 as
\r
313 * "12,34,56,789".
\r
315 * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the
\r
316 * prefix, before the suffix, after the suffix, or not at all.
\r
318 * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding
\r
325 * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal
\r
326 * digits, as defined by {@link UCharacter#digit}. In addition,
\r
327 * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters
\r
328 * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}
\r
329 * object. During formatting, the {@link DecimalFormatSymbols}-based digits are output.
\r
331 * <p>During parsing, grouping separators are ignored.
\r
333 * <p>For currency parsing, the formatter is able to parse every currency style formats no
\r
334 * matter which style the formatter is constructed with. For example, a formatter
\r
335 * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can
\r
336 * parse formats such as "USD1.00" and "3.00 US dollars".
\r
338 * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns
\r
339 * <code>null</code> and leaves the parse position unchanged. The convenience method
\r
340 * {@link #parse(String)} indicates parse failure by throwing a {@link
\r
341 * java.text.ParseException}.
\r
343 * <h4>Formatting</h4>
\r
345 * <p>Formatting is guided by several parameters, all of which can be specified either
\r
346 * using a pattern or using the API. The following description applies to formats that do
\r
347 * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant
\r
350 * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer
\r
351 * digits</em>, then only the least significant digits are shown. For example, 1997 is
\r
352 * formatted as "97" if the maximum integer digits is set to 2.
\r
354 * <li>If the number of actual integer digits is less than the <em>minimum integer
\r
355 * digits</em>, then leading zeros are added. For example, 1997 is formatted as "01997"
\r
356 * if the minimum integer digits is set to 5.
\r
358 * <li>If the number of actual fraction digits exceeds the <em>maximum fraction
\r
359 * digits</em>, then half-even rounding it performed to the maximum fraction digits. For
\r
360 * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2. This
\r
361 * behavior can be changed by specifying a rounding increment and a rounding mode.
\r
363 * <li>If the number of actual fraction digits is less than the <em>minimum fraction
\r
364 * digits</em>, then trailing zeros are added. For example, 0.125 is formatted as
\r
365 * "0.1250" if the mimimum fraction digits is set to 4.
\r
367 * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions
\r
368 * after the decimal, where <em>j</em> is less than the maximum fraction digits. For
\r
369 * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.
\r
372 * <p><strong>Special Values</strong>
\r
374 * <p><code>NaN</code> is represented as a single character, typically
\r
375 * <code>\uFFFD</code>. This character is determined by the {@link
\r
376 * DecimalFormatSymbols} object. This is the only value for which the prefixes and
\r
377 * suffixes are not used.
\r
379 * <p>Infinity is represented as a single character, typically <code>\u221E</code>,
\r
380 * with the positive or negative prefixes and suffixes applied. The infinity character is
\r
381 * determined by the {@link DecimalFormatSymbols} object.
\r
383 * <a name="sci"><h4>Scientific Notation</h4></a>
\r
385 * <p>Numbers in scientific notation are expressed as the product of a mantissa and a
\r
386 * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
\r
387 * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
\r
388 * but it need not be. <code>DecimalFormat</code> supports arbitrary mantissas.
\r
389 * <code>DecimalFormat</code> can be instructed to use scientific notation through the API
\r
390 * or through the pattern. In a pattern, the exponent character immediately followed by
\r
391 * one or more digit characters indicates scientific notation. Example: "0.###E0" formats
\r
392 * the number 1234 as "1.234E3".
\r
396 * <li>The number of digit characters after the exponent character gives the minimum
\r
397 * exponent digit count. There is no maximum. Negative exponents are formatted using the
\r
398 * localized minus sign, <em>not</em> the prefix and suffix from the pattern. This allows
\r
399 * patterns such as "0.###E0 m/s". To prefix positive exponents with a localized plus
\r
400 * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats
\r
401 * "1E+1", "1E+0", "1E-1", etc. (In localized patterns, use the localized plus sign
\r
402 * rather than '+'.)
\r
404 * <li>The minimum number of integer digits is achieved by adjusting the exponent.
\r
405 * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4". This only happens if
\r
406 * there is no maximum number of integer digits. If there is a maximum, then the minimum
\r
407 * number of integer digits is fixed at one.
\r
409 * <li>The maximum number of integer digits, if present, specifies the exponent grouping.
\r
410 * The most common use of this is to generate <em>engineering notation</em>, in which the
\r
411 * exponent is a multiple of three, e.g., "##0.###E0". The number 12345 is formatted
\r
412 * using "##0.####E0" as "12.345E3".
\r
414 * <li>When using scientific notation, the formatter controls the digit counts using
\r
415 * significant digits logic. The maximum number of significant digits limits the total
\r
416 * number of integer and fraction digits that will be shown in the mantissa; it does not
\r
417 * affect parsing. For example, 12345 formatted with "##0.##E0" is "12.3E3". See the
\r
418 * section on significant digits for more details.
\r
420 * <li>The number of significant digits shown is determined as follows: If
\r
421 * areSignificantDigitsUsed() returns false, then the minimum number of significant digits
\r
422 * shown is one, and the maximum number of significant digits shown is the sum of the
\r
423 * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the
\r
424 * maximum integer digits. If this sum is zero, then all significant digits are shown.
\r
425 * If areSignificantDigitsUsed() returns true, then the significant digit counts are
\r
426 * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits(). In this
\r
427 * case, the number of integer digits is fixed at one, and there is no exponent grouping.
\r
429 * <li>Exponential patterns may not contain grouping separators.
\r
433 * <a name="sigdig"><h4>Significant Digits</h4></a>
\r
435 * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)
\r
436 * significant digits counts, or (b) integer and fraction digit counts. Integer and
\r
437 * fraction digit counts are described above. When a formatter is using significant
\r
438 * digits counts, the number of integer and fraction digits is not specified directly, and
\r
439 * the formatter settings for these counts are ignored. Instead, the formatter uses
\r
440 * however many integer and fraction digits are required to display the specified number
\r
441 * of significant digits. Examples:
\r
444 * <table border=0 cellspacing=3 cellpadding=0>
\r
445 * <tr bgcolor="#ccccff">
\r
446 * <th align=left>Pattern
\r
447 * <th align=left>Minimum significant digits
\r
448 * <th align=left>Maximum significant digits
\r
449 * <th align=left>Number
\r
450 * <th align=left>Output of format()
\r
452 * <td><code>@@@</code>
\r
456 * <td><code>12300</code>
\r
457 * <tr valign=top bgcolor="#eeeeff">
\r
458 * <td><code>@@@</code>
\r
462 * <td><code>0.123</code>
\r
464 * <td><code>@@##</code>
\r
468 * <td><code>3.142</code>
\r
469 * <tr valign=top bgcolor="#eeeeff">
\r
470 * <td><code>@@##</code>
\r
474 * <td><code>1.23</code>
\r
480 * <li>Significant digit counts may be expressed using patterns that specify a minimum and
\r
481 * maximum number of significant digits. These are indicated by the <code>'@'</code> and
\r
482 * <code>'#'</code> characters. The minimum number of significant digits is the number of
\r
483 * <code>'@'</code> characters. The maximum number of significant digits is the number of
\r
484 * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on
\r
485 * the right. For example, the pattern <code>"@@@"</code> indicates exactly 3 significant
\r
486 * digits. The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.
\r
487 * Trailing zero digits to the right of the decimal separator are suppressed after the
\r
488 * minimum number of significant digits have been shown. For example, the pattern
\r
489 * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.
\r
491 * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor
\r
492 * the <code>'0'</code> pattern character. Patterns such as <code>"@00"</code> or
\r
493 * <code>"@.###"</code> are disallowed.
\r
495 * <li>Any number of <code>'#'</code> characters may be prepended to the left of the
\r
496 * leftmost <code>'@'</code> character. These have no effect on the minimum and maximum
\r
497 * significant digits counts, but may be used to position grouping separators. For
\r
498 * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum
\r
499 * of two significant digits, and a grouping size of three.
\r
501 * <li>In order to enable significant digits formatting, use a pattern containing the
\r
502 * <code>'@'</code> pattern character. Alternatively, call {@link
\r
503 * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
\r
505 * <li>In order to disable significant digits formatting, use a pattern that does not
\r
506 * contain the <code>'@'</code> pattern character. Alternatively, call {@link
\r
507 * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.
\r
509 * <li>The number of significant digits has no effect on parsing.
\r
511 * <li>Significant digits may be used together with exponential notation. Such patterns
\r
512 * are equivalent to a normal exponential pattern with a minimum and maximum integer digit
\r
513 * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -
\r
514 * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -
\r
515 * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to
\r
516 * <code>"0.0###E0"</code>.
\r
518 * <li>If signficant digits are in use, then the integer and fraction digit counts, as set
\r
519 * via the API, are ignored. If significant digits are not in use, then the signficant
\r
520 * digit counts, as set via the API, are ignored.
\r
526 * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a
\r
527 * specific width. Padding may be specified either through the API or through the pattern
\r
528 * syntax. In a pattern the pad escape character, followed by a single pad character,
\r
529 * causes padding to be parsed and formatted. The pad escape character is '*' in
\r
530 * unlocalized patterns, and can be localized using {@link
\r
531 * DecimalFormatSymbols#setPadEscape}. For example, <code>"$*x#,##0.00"</code> formats
\r
532 * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.
\r
536 * <li>When padding is in effect, the width of the positive subpattern, including prefix
\r
537 * and suffix, determines the format width. For example, in the pattern <code>"* #0
\r
538 * o''clock"</code>, the format width is 10.
\r
540 * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
\r
542 * <li>Some parameters which usually do not matter have meaning when padding is used,
\r
543 * because the pattern width is significant with padding. In the pattern "*
\r
544 * ##,##,#,##0.##", the format width is 14. The initial characters "##,##," do not affect
\r
545 * the grouping size or maximum integer digits, but they do affect the format width.
\r
547 * <li>Padding may be inserted at one of four locations: before the prefix, after the
\r
548 * prefix, before the suffix, or after the suffix. If padding is specified in any other
\r
549 * location, {@link #applyPattern} throws an {@link IllegalArgumentException}. If there
\r
550 * is no prefix, before the prefix and after the prefix are equivalent, likewise for the
\r
553 * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the
\r
554 * pad escape is the pad character. This may be any character, including a special pattern
\r
555 * character. That is, the pad escape <em>escapes</em> the following character. If there
\r
556 * is no character after the pad escape, then the pattern is illegal.
\r
561 * <strong>Rounding</strong>
\r
563 * <p><code>DecimalFormat</code> supports rounding to a specific increment. For example,
\r
564 * 1230 rounded to the nearest 50 is 1250. 1.234 rounded to the nearest 0.65 is 1.3. The
\r
565 * rounding increment may be specified through the API or in a pattern. To specify a
\r
566 * rounding increment in a pattern, include the increment in the pattern itself. "#,#50"
\r
567 * specifies a rounding increment of 50. "#,##0.05" specifies a rounding increment of
\r
572 * <li>Rounding only affects the string produced by formatting. It does not affect
\r
573 * parsing or change any numerical values.
\r
575 * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link
\r
576 * com.ibm.icu.math.BigDecimal} documentation for a description of the modes. Rounding
\r
577 * increments specified in patterns use the default mode, {@link
\r
578 * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
\r
580 * <li>Some locales use rounding in their currency formats to reflect the smallest
\r
581 * currency denomination.
\r
583 * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave
\r
584 * identically to digit '0'.
\r
588 * <h4>Synchronization</h4>
\r
590 * <p><code>DecimalFormat</code> objects are not synchronized. Multiple threads should
\r
591 * not access one formatter concurrently.
\r
593 * @see java.text.Format
\r
594 * @see NumberFormat
\r
595 * @author Mark Davis
\r
599 public class DecimalFormat extends NumberFormat {
\r
602 * Creates a DecimalFormat using the default pattern and symbols for the default
\r
603 * locale. This is a convenient way to obtain a DecimalFormat when
\r
604 * internationalization is not the main concern.
\r
606 * <p>To obtain standard formats for a given locale, use the factory methods on
\r
607 * NumberFormat such as getNumberInstance. These factories will return the most
\r
608 * appropriate sub-class of NumberFormat for a given locale.
\r
610 * @see NumberFormat#getInstance
\r
611 * @see NumberFormat#getNumberInstance
\r
612 * @see NumberFormat#getCurrencyInstance
\r
613 * @see NumberFormat#getPercentInstance
\r
616 public DecimalFormat() {
\r
617 ULocale def = ULocale.getDefault();
\r
618 String pattern = getPattern(def, 0);
\r
619 // Always applyPattern after the symbols are set
\r
620 this.symbols = new DecimalFormatSymbols(def);
\r
621 setCurrency(Currency.getInstance(def));
\r
622 applyPatternWithoutExpandAffix(pattern, false);
\r
623 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
624 currencyPluralInfo = new CurrencyPluralInfo(def);
\r
625 // the exact pattern is not known until the plural count is known.
\r
626 // so, no need to expand affix now.
\r
628 expandAffixAdjustWidth(null);
\r
633 * Creates a DecimalFormat from the given pattern and the symbols for the default
\r
634 * locale. This is a convenient way to obtain a DecimalFormat when
\r
635 * internationalization is not the main concern.
\r
637 * <p>To obtain standard formats for a given locale, use the factory methods on
\r
638 * NumberFormat such as getNumberInstance. These factories will return the most
\r
639 * appropriate sub-class of NumberFormat for a given locale.
\r
641 * @param pattern A non-localized pattern string.
\r
642 * @throws IllegalArgumentException if the given pattern is invalid.
\r
643 * @see NumberFormat#getInstance
\r
644 * @see NumberFormat#getNumberInstance
\r
645 * @see NumberFormat#getCurrencyInstance
\r
646 * @see NumberFormat#getPercentInstance
\r
649 public DecimalFormat(String pattern) {
\r
650 // Always applyPattern after the symbols are set
\r
651 ULocale def = ULocale.getDefault();
\r
652 this.symbols = new DecimalFormatSymbols(def);
\r
653 setCurrency(Currency.getInstance(def));
\r
654 applyPatternWithoutExpandAffix(pattern, false);
\r
655 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
656 currencyPluralInfo = new CurrencyPluralInfo(def);
\r
658 expandAffixAdjustWidth(null);
\r
663 * Creates a DecimalFormat from the given pattern and symbols. Use this constructor
\r
664 * when you need to completely customize the behavior of the format.
\r
666 * <p>To obtain standard formats for a given locale, use the factory methods on
\r
667 * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor
\r
668 * adjustments to a standard format, you can modify the format returned by a
\r
669 * NumberFormat factory method.
\r
671 * @param pattern a non-localized pattern string
\r
672 * @param symbols the set of symbols to be used
\r
673 * @exception IllegalArgumentException if the given pattern is invalid
\r
674 * @see NumberFormat#getInstance
\r
675 * @see NumberFormat#getNumberInstance
\r
676 * @see NumberFormat#getCurrencyInstance
\r
677 * @see NumberFormat#getPercentInstance
\r
678 * @see DecimalFormatSymbols
\r
681 public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
\r
682 createFromPatternAndSymbols(pattern, symbols);
\r
685 private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
\r
686 // Always applyPattern after the symbols are set
\r
687 symbols = (DecimalFormatSymbols) inputSymbols.clone();
\r
688 setCurrencyForSymbols();
\r
689 applyPatternWithoutExpandAffix(pattern, false);
\r
690 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
691 currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
\r
693 expandAffixAdjustWidth(null);
\r
698 * Creates a DecimalFormat from the given pattern, symbols, information used for
\r
699 * currency plural format, and format style. Use this constructor when you need to
\r
700 * completely customize the behavior of the format.
\r
702 * <p>To obtain standard formats for a given locale, use the factory methods on
\r
703 * NumberFormat such as getInstance or getCurrencyInstance.
\r
705 * <p>If you need only minor adjustments to a standard format, you can modify the
\r
706 * format returned by a NumberFormat factory method using the setters.
\r
708 * <p>If you want to completely customize a decimal format, using your own
\r
709 * DecimalFormatSymbols (such as group separators) and your own information for
\r
710 * currency plural formatting (such as plural rule and currency plural patterns), you
\r
711 * can use this constructor.
\r
713 * @param pattern a non-localized pattern string
\r
714 * @param symbols the set of symbols to be used
\r
715 * @param infoInput the information used for currency plural format, including
\r
716 * currency plural patterns and plural rules.
\r
717 * @param style the decimal formatting style, it is one of the following values:
\r
718 * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
\r
719 * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;
\r
720 * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;
\r
723 public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,
\r
725 CurrencyPluralInfo info = infoInput;
\r
726 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
727 info = (CurrencyPluralInfo) infoInput.clone();
\r
729 create(pattern, symbols, info, style);
\r
732 private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info,
\r
734 if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
\r
735 createFromPatternAndSymbols(pattern, inputSymbols);
\r
737 // Always applyPattern after the symbols are set
\r
738 symbols = (DecimalFormatSymbols) inputSymbols.clone();
\r
739 currencyPluralInfo = info;
\r
740 // the pattern used in format is not fixed until formatting, in which, the
\r
741 // number is known and will be used to pick the right pattern based on plural
\r
742 // count. Here, set the pattern as the pattern of plural count == "other".
\r
743 // For most locale, the patterns are probably the same for all plural
\r
744 // count. If not, the right pattern need to be re-applied during format.
\r
745 String currencyPluralPatternForOther =
\r
746 currencyPluralInfo.getCurrencyPluralPattern("other");
\r
747 applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false);
\r
748 setCurrencyForSymbols();
\r
750 style = inputStyle;
\r
754 * Creates a DecimalFormat for currency plural format from the given pattern, symbols,
\r
757 DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
\r
758 CurrencyPluralInfo info = null;
\r
759 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
760 info = new CurrencyPluralInfo(inputSymbols.getLocale());
\r
762 create(pattern, inputSymbols, info, style);
\r
769 public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
\r
770 return format(number, result, fieldPosition, false);
\r
773 // [Spark/CDL] The actual method to format number. If boolean value
\r
774 // parseAttr == true, then attribute information will be recorded.
\r
775 private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition,
\r
776 boolean parseAttr) {
\r
777 fieldPosition.setBeginIndex(0);
\r
778 fieldPosition.setEndIndex(0);
\r
780 if (Double.isNaN(number)) {
\r
781 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
782 fieldPosition.setBeginIndex(result.length());
\r
783 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
784 fieldPosition.setBeginIndex(result.length());
\r
787 result.append(symbols.getNaN());
\r
788 // [Spark/CDL] Add attribute for NaN here.
\r
789 // result.append(symbols.getNaN());
\r
791 addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(),
\r
794 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
795 fieldPosition.setEndIndex(result.length());
\r
796 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
797 fieldPosition.setEndIndex(result.length());
\r
800 addPadding(result, fieldPosition, 0, 0);
\r
804 // Do this BEFORE checking to see if value is infinite or negative!
\r
805 if (multiplier != 1)
\r
806 number *= multiplier;
\r
809 // Detecting whether a double is negative is easy with the exception of the value
\r
810 // -0.0. This is a double which has a zero mantissa (and exponent), but a negative
\r
811 // sign bit. It is semantically distinct from a zero with a positive sign bit, and
\r
812 // this distinction is important to certain kinds of computations. However, it's a
\r
813 // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you
\r
814 // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
\r
815 // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by
\r
816 // bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
\r
817 boolean isNegative = (number < 0.0) || (number == 0.0 && 1 / number < 0.0);
\r
821 // Apply rounding after multiplier
\r
822 if (roundingDouble > 0.0) {
\r
823 // number = roundingDouble
\r
824 // * round(number / roundingDouble, roundingMode, isNegative);
\r
825 double newNumber = round(number, roundingDouble, roundingDoubleReciprocal, roundingMode,
\r
827 if (newNumber == 0.0 && number != newNumber)
\r
828 isNegative = false; // if we touched it, then make zero be zero.
\r
829 number = newNumber;
\r
832 if (Double.isInfinite(number)) {
\r
833 int prefixLen = appendAffix(result, isNegative, true, parseAttr);
\r
835 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
836 fieldPosition.setBeginIndex(result.length());
\r
837 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
838 fieldPosition.setBeginIndex(result.length());
\r
841 // [Spark/CDL] Add attribute for infinity here.
\r
842 result.append(symbols.getInfinity());
\r
844 addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(),
\r
847 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
848 fieldPosition.setEndIndex(result.length());
\r
849 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
850 fieldPosition.setEndIndex(result.length());
\r
853 int suffixLen = appendAffix(result, isNegative, false, parseAttr);
\r
855 addPadding(result, fieldPosition, prefixLen, suffixLen);
\r
859 // At this point we are guaranteed a nonnegative finite
\r
861 synchronized (digitList) {
\r
862 digitList.set(number, precision(false), !useExponentialNotation &&
\r
863 !areSignificantDigitsUsed());
\r
864 return subformat(number, result, fieldPosition, isNegative, false, parseAttr);
\r
869 * Round a double value to the nearest multiple of the given rounding increment,
\r
870 * according to the given mode. This is equivalent to rounding value/roundingInc to
\r
871 * the nearest integer, according to the given mode, and returning that integer *
\r
872 * roundingInc. Note this is changed from the version in 2.4, since division of
\r
873 * doubles have inaccuracies. jitterbug 1871.
\r
876 * the absolute value of the number to be rounded
\r
877 * @param roundingInc
\r
878 * the rounding increment
\r
879 * @param roundingIncReciprocal
\r
880 * if non-zero, is the
\r
882 * a BigDecimal rounding mode
\r
883 * @param isNegative
\r
884 * true if the number to be rounded is negative
\r
885 * @return the absolute value of the rounded result
\r
887 private static double round(double number, double roundingInc, double roundingIncReciprocal,
\r
888 int mode, boolean isNegative) {
\r
890 double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number *
\r
891 roundingIncReciprocal;
\r
893 // do the absolute cases first
\r
896 case BigDecimal.ROUND_CEILING:
\r
897 div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
\r
899 case BigDecimal.ROUND_FLOOR:
\r
900 div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
\r
902 case BigDecimal.ROUND_DOWN:
\r
903 div = (Math.floor(div + epsilon));
\r
905 case BigDecimal.ROUND_UP:
\r
906 div = (Math.ceil(div - epsilon));
\r
908 case BigDecimal.ROUND_UNNECESSARY:
\r
909 if (div != Math.floor(div)) {
\r
910 throw new ArithmeticException("Rounding necessary");
\r
915 // Handle complex cases, where the choice depends on the closer value.
\r
917 // We figure out the distances to the two possible values, ceiling and floor.
\r
918 // We then go for the diff that is smaller. Only if they are equal does the
\r
921 double ceil = Math.ceil(div);
\r
922 double ceildiff = ceil - div; // (ceil * roundingInc) - number;
\r
923 double floor = Math.floor(div);
\r
924 double floordiff = div - floor; // number - (floor * roundingInc);
\r
926 // Note that the diff values were those mapped back to the "normal" space by
\r
927 // using the roundingInc. I don't have access to the original author of the
\r
928 // code but suspect that that was to produce better result in edge cases
\r
929 // because of machine precision, rather than simply using the difference
\r
930 // between, say, ceil and div. However, it didn't work in all cases. Am
\r
931 // trying instead using an epsilon value.
\r
934 case BigDecimal.ROUND_HALF_EVEN:
\r
935 // We should be able to just return Math.rint(a), but this
\r
936 // doesn't work in some VMs.
\r
937 // if one is smaller than the other, take the corresponding side
\r
938 if (floordiff + epsilon < ceildiff) {
\r
940 } else if (ceildiff + epsilon < floordiff) {
\r
942 } else { // they are equal, so we want to round to whichever is even
\r
943 double testFloor = floor / 2;
\r
944 div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
\r
947 case BigDecimal.ROUND_HALF_DOWN:
\r
948 div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
\r
950 case BigDecimal.ROUND_HALF_UP:
\r
951 div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
\r
954 throw new IllegalArgumentException("Invalid rounding mode: " + mode);
\r
957 number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal;
\r
961 private static double epsilon = 0.00000000001;
\r
966 // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
\r
967 public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
\r
968 return format(number, result, fieldPosition, false);
\r
971 private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition,
\r
972 boolean parseAttr) {
\r
973 fieldPosition.setBeginIndex(0);
\r
974 fieldPosition.setEndIndex(0);
\r
976 // If we are to do rounding, we need to move into the BigDecimal
\r
977 // domain in order to do divide/multiply correctly.
\r
978 if (roundingIncrementICU != null) {
\r
979 return format(BigDecimal.valueOf(number), result, fieldPosition);
\r
982 boolean isNegative = (number < 0);
\r
986 // In general, long values always represent real finite numbers, so we don't have
\r
987 // to check for +/- Infinity or NaN. However, there is one case we have to be
\r
988 // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE
\r
989 // outside the legal range. We check for this before multiplying, and if it
\r
990 // happens we use BigInteger instead.
\r
991 if (multiplier != 1) {
\r
992 boolean tooBig = false;
\r
993 if (number < 0) { // This can only happen if number == Long.MIN_VALUE
\r
994 long cutoff = Long.MIN_VALUE / multiplier;
\r
995 tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
\r
997 long cutoff = Long.MAX_VALUE / multiplier;
\r
998 tooBig = (number > cutoff);
\r
1001 // [Spark/CDL] Use
\r
1002 // format_BigInteger_StringBuffer_FieldPosition_boolean instead
\r
1003 // parseAttr is used to judge whether to synthesize attributes.
\r
1004 return format(BigInteger.valueOf(isNegative ? -number : number), result,
\r
1005 fieldPosition, parseAttr);
\r
1009 number *= multiplier;
\r
1010 synchronized (digitList) {
\r
1011 digitList.set(number, precision(true));
\r
1012 return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
\r
1017 * Formats a BigInteger number.
\r
1021 public StringBuffer format(BigInteger number, StringBuffer result,
\r
1022 FieldPosition fieldPosition) {
\r
1023 return format(number, result, fieldPosition, false);
\r
1026 private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition,
\r
1027 boolean parseAttr) {
\r
1028 // If we are to do rounding, we need to move into the BigDecimal
\r
1029 // domain in order to do divide/multiply correctly.
\r
1030 if (roundingIncrementICU != null) {
\r
1031 return format(new BigDecimal(number), result, fieldPosition);
\r
1034 if (multiplier != 1) {
\r
1035 number = number.multiply(BigInteger.valueOf(multiplier));
\r
1038 // At this point we are guaranteed a nonnegative finite
\r
1040 synchronized (digitList) {
\r
1041 digitList.set(number, precision(true));
\r
1042 return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
\r
1048 * Formats a BigDecimal number.
\r
1052 public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
\r
1053 FieldPosition fieldPosition) {
\r
1054 return format(number, result, fieldPosition, false);
\r
1057 private StringBuffer format(java.math.BigDecimal number, StringBuffer result,
\r
1058 FieldPosition fieldPosition,
\r
1059 boolean parseAttr) {
\r
1060 if (multiplier != 1) {
\r
1061 number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
\r
1064 if (roundingIncrement != null) {
\r
1065 number = number.divide(roundingIncrement, 0, roundingMode).multiply(roundingIncrement);
\r
1068 synchronized (digitList) {
\r
1069 digitList.set(number, precision(false), !useExponentialNotation &&
\r
1070 !areSignificantDigitsUsed());
\r
1071 return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
\r
1072 false, parseAttr);
\r
1077 * Formats a BigDecimal number.
\r
1081 public StringBuffer format(BigDecimal number, StringBuffer result,
\r
1082 FieldPosition fieldPosition) {
\r
1083 // This method is just a copy of the corresponding java.math.BigDecimal method
\r
1084 // for now. It isn't very efficient since it must create a conversion object to
\r
1085 // do math on the rounding increment. In the future we may try to clean this up,
\r
1086 // or even better, limit our support to just one flavor of BigDecimal.
\r
1087 if (multiplier != 1) {
\r
1088 number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
\r
1091 if (roundingIncrementICU != null) {
\r
1092 number = number.divide(roundingIncrementICU, 0, roundingMode)
\r
1093 .multiply(roundingIncrementICU, mathContext);
\r
1096 synchronized (digitList) {
\r
1097 digitList.set(number, precision(false), !useExponentialNotation &&
\r
1098 !areSignificantDigitsUsed());
\r
1099 return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
\r
1105 * Returns true if a grouping separator belongs at the given position, based on whether
\r
1106 * grouping is in use and the values of the primary and secondary grouping interval.
\r
1108 * @param pos the number of integer digits to the right of the current position. Zero
\r
1109 * indicates the position after the rightmost integer digit.
\r
1110 * @return true if a grouping character belongs at the current position.
\r
1112 private boolean isGroupingPosition(int pos) {
\r
1113 boolean result = false;
\r
1114 if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
\r
1115 if ((groupingSize2 > 0) && (pos > groupingSize)) {
\r
1116 result = ((pos - groupingSize) % groupingSize2) == 0;
\r
1118 result = pos % groupingSize == 0;
\r
1125 * Return the number of fraction digits to display, or the total
\r
1126 * number of digits for significant digit formats and exponential
\r
1129 private int precision(boolean isIntegral) {
\r
1130 if (areSignificantDigitsUsed()) {
\r
1131 return getMaximumSignificantDigits();
\r
1132 } else if (useExponentialNotation) {
\r
1133 return getMinimumIntegerDigits() + getMaximumFractionDigits();
\r
1135 return isIntegral ? 0 : getMaximumFractionDigits();
\r
1139 private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition,
\r
1140 boolean isNegative, boolean isInteger, boolean parseAttr) {
\r
1141 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
1142 return subformat(currencyPluralInfo.select(number), result, fieldPosition, isNegative,
\r
1143 isInteger, parseAttr);
\r
1145 return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
\r
1149 private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition,
\r
1150 boolean isNegative,
\r
1151 boolean isInteger, boolean parseAttr) {
\r
1152 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
1153 return subformat(currencyPluralInfo.select(number), result, fieldPosition, isNegative,
\r
1154 isInteger, parseAttr);
\r
1156 return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
\r
1160 private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition,
\r
1161 boolean isNegative, boolean isInteger, boolean parseAttr) {
\r
1162 // There are 2 ways to activate currency plural format: by applying a pattern with
\r
1163 // 3 currency sign directly, or by instantiate a decimal formatter using
\r
1164 // PLURALCURRENCYSTYLE. For both cases, the number of currency sign in the
\r
1165 // pattern is 3. Even if the number of currency sign in the pattern is 3, it does
\r
1166 // not mean we need to reset the pattern. For 1st case, we do not need to reset
\r
1167 // pattern. For 2nd case, we might need to reset pattern, if the default pattern
\r
1168 // (corresponding to plural count 'other') we use is different from the pattern
\r
1169 // based on 'pluralCount'.
\r
1171 // style is only valid when decimal formatter is constructed through
\r
1172 // DecimalFormat(pattern, symbol, style)
\r
1173 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
1174 // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
\r
1175 String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
\r
1176 if (formatPattern.equals(currencyPluralPattern) == false) {
\r
1177 applyPatternWithoutExpandAffix(currencyPluralPattern, false);
\r
1180 // Expand the affix to the right name according to the plural rule. This is only
\r
1181 // used for currency plural formatting. Currency plural name is not a fixed
\r
1182 // static one, it is a dynamic name based on the currency plural count. So, the
\r
1183 // affixes need to be expanded here. For other cases, the affix is a static one
\r
1184 // based on pattern alone, and it is already expanded during applying pattern, or
\r
1185 // setDecimalFormatSymbols, or setCurrency.
\r
1186 expandAffixAdjustWidth(pluralCount);
\r
1187 return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
\r
1191 * Complete the formatting of a finite number. On entry, the
\r
1192 * digitList must be filled in with the correct digits.
\r
1194 private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,
\r
1195 boolean isNegative, boolean isInteger, boolean parseAttr) {
\r
1196 // NOTE: This isn't required anymore because DigitList takes care of this.
\r
1198 // // The negative of the exponent represents the number of leading // zeros
\r
1199 // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g.,
\r
1200 // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction
\r
1201 // digits, then we have an underflow // for the printed representation. We
\r
1202 // recognize this here and set // the DigitList representation to zero in this
\r
1205 // if (-digitList.decimalAt >= getMaximumFractionDigits())
\r
1207 // digitList.count = 0;
\r
1211 char zero = symbols.getZeroDigit();
\r
1212 int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
\r
1213 char grouping = currencySignCount > 0 ? symbols.getMonetaryGroupingSeparator() :
\r
1214 symbols.getGroupingSeparator();
\r
1215 char decimal = currencySignCount > 0 ? symbols.getMonetaryDecimalSeparator() :
\r
1216 symbols.getDecimalSeparator();
\r
1217 boolean useSigDig = areSignificantDigitsUsed();
\r
1218 int maxIntDig = getMaximumIntegerDigits();
\r
1219 int minIntDig = getMinimumIntegerDigits();
\r
1221 // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as
\r
1222 // zero. This allows sensible computations and preserves relations such as
\r
1223 // signum(1/x) = signum(x), where x is +Infinity or -Infinity. Prior to this fix,
\r
1224 // we always formatted zero values as if they were positive. Liu 7/6/98.
\r
1225 if (digitList.isZero()) {
\r
1226 digitList.decimalAt = 0; // Normalize
\r
1229 int prefixLen = appendAffix(result, isNegative, true, parseAttr);
\r
1231 if (useExponentialNotation) {
\r
1232 // Record field information for caller.
\r
1233 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1234 fieldPosition.setBeginIndex(result.length());
\r
1235 fieldPosition.setEndIndex(-1);
\r
1236 } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1237 fieldPosition.setBeginIndex(-1);
\r
1238 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1239 fieldPosition.setBeginIndex(result.length());
\r
1240 fieldPosition.setEndIndex(-1);
\r
1241 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1242 fieldPosition.setBeginIndex(-1);
\r
1246 // the begin index of integer part
\r
1247 // the end index of integer part
\r
1248 // the begin index of fractional part
\r
1249 int intBegin = result.length();
\r
1251 int fracBegin = -1;
\r
1252 int minFracDig = 0;
\r
1254 maxIntDig = minIntDig = 1;
\r
1255 minFracDig = getMinimumSignificantDigits() - 1;
\r
1257 minFracDig = getMinimumFractionDigits();
\r
1258 if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
\r
1260 if (maxIntDig < minIntDig) {
\r
1261 maxIntDig = minIntDig;
\r
1264 if (maxIntDig > minIntDig) {
\r
1269 // Minimum integer digits are handled in exponential format by adjusting the
\r
1270 // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".
\r
1272 // Maximum integer digits are interpreted as indicating the repeating
\r
1273 // range. This is useful for engineering notation, in which the exponent is
\r
1274 // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer
\r
1275 // digits is "12.34e-3". If maximum integer digits are defined and are larger
\r
1276 // than minimum integer digits, then minimum integer digits are ignored.
\r
1278 int exponent = digitList.decimalAt;
\r
1279 if (maxIntDig > 1 && maxIntDig != minIntDig) {
\r
1280 // A exponent increment is defined; adjust to it.
\r
1281 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1;
\r
1282 exponent *= maxIntDig;
\r
1284 // No exponent increment is defined; use minimum integer digits.
\r
1285 // If none is specified, as in "#E0", generate 1 integer digit.
\r
1286 exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1;
\r
1289 // We now output a minimum number of digits, and more if there are more
\r
1290 // digits, up to the maximum number of digits. We place the decimal point
\r
1291 // after the "integer" digits, which are the first (decimalAt - exponent)
\r
1293 int minimumDigits = minIntDig + minFracDig;
\r
1294 // The number of integer digits is handled specially if the number
\r
1295 // is zero, since then there may be no digits.
\r
1296 int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent;
\r
1297 int totalDigits = digitList.count;
\r
1298 if (minimumDigits > totalDigits)
\r
1299 totalDigits = minimumDigits;
\r
1300 if (integerDigits > totalDigits)
\r
1301 totalDigits = integerDigits;
\r
1303 for (i = 0; i < totalDigits; ++i) {
\r
1304 if (i == integerDigits) {
\r
1305 // Record field information for caller.
\r
1306 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1307 fieldPosition.setEndIndex(result.length());
\r
1308 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1309 fieldPosition.setEndIndex(result.length());
\r
1312 // [Spark/CDL] Add attribute for integer part
\r
1314 intEnd = result.length();
\r
1315 addAttribute(Field.INTEGER, intBegin, result.length());
\r
1317 result.append(decimal);
\r
1318 // [Spark/CDL] Add attribute for decimal separator
\r
1320 // Length of decimal separator is 1.
\r
1321 int decimalSeparatorBegin = result.length() - 1;
\r
1322 addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin,
\r
1324 fracBegin = result.length();
\r
1326 // Record field information for caller.
\r
1327 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1328 fieldPosition.setBeginIndex(result.length());
\r
1329 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1330 fieldPosition.setBeginIndex(result.length());
\r
1333 result.append((i < digitList.count)
\r
1334 ? (char) (digitList.digits[i] + zeroDelta)
\r
1338 // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
\r
1339 if (digitList.isZero() && (totalDigits == 0)) {
\r
1340 result.append(zero);
\r
1343 // Record field information
\r
1344 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1345 if (fieldPosition.getEndIndex() < 0) {
\r
1346 fieldPosition.setEndIndex(result.length());
\r
1348 } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1349 if (fieldPosition.getBeginIndex() < 0) {
\r
1350 fieldPosition.setBeginIndex(result.length());
\r
1352 fieldPosition.setEndIndex(result.length());
\r
1353 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1354 if (fieldPosition.getEndIndex() < 0) {
\r
1355 fieldPosition.setEndIndex(result.length());
\r
1357 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1358 if (fieldPosition.getBeginIndex() < 0) {
\r
1359 fieldPosition.setBeginIndex(result.length());
\r
1361 fieldPosition.setEndIndex(result.length());
\r
1364 // [Spark/CDL] Calcuate the end index of integer part and fractional
\r
1365 // part if they are not properly processed yet.
\r
1368 addAttribute(Field.INTEGER, intBegin, result.length());
\r
1370 if (fracBegin > 0) {
\r
1371 addAttribute(Field.FRACTION, fracBegin, result.length());
\r
1375 // The exponent is output using the pattern-specified minimum exponent
\r
1376 // digits. There is no maximum limit to the exponent digits, since truncating
\r
1377 // the exponent would result in an unacceptable inaccuracy.
\r
1378 result.append(symbols.getExponentSeparator());
\r
1379 // [Spark/CDL] For exponent symbol, add an attribute.
\r
1381 addAttribute(Field.EXPONENT_SYMBOL, result.length() -
\r
1382 symbols.getExponentSeparator().length(), result.length());
\r
1384 // For zero values, we force the exponent to zero. We must do this here, and
\r
1385 // not earlier, because the value is used to determine integer digit count
\r
1387 if (digitList.isZero())
\r
1390 boolean negativeExponent = exponent < 0;
\r
1391 if (negativeExponent) {
\r
1392 exponent = -exponent;
\r
1393 result.append(symbols.getMinusSign());
\r
1394 // [Spark/CDL] If exponent has sign, then add an exponent sign
\r
1397 // Length of exponent sign is 1.
\r
1398 addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
\r
1400 } else if (exponentSignAlwaysShown) {
\r
1401 result.append(symbols.getPlusSign());
\r
1402 // [Spark/CDL] Add an plus sign attribute.
\r
1404 // Length of exponent sign is 1.
\r
1405 int expSignBegin = result.length() - 1;
\r
1406 addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length());
\r
1409 int expBegin = result.length();
\r
1410 digitList.set(exponent);
\r
1412 int expDig = minExponentDigits;
\r
1413 if (useExponentialNotation && expDig < 1) {
\r
1416 for (i = digitList.decimalAt; i < expDig; ++i)
\r
1417 result.append(zero);
\r
1419 for (i = 0; i < digitList.decimalAt; ++i) {
\r
1420 result.append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta)
\r
1423 // [Spark/CDL] Add attribute for exponent part.
\r
1425 addAttribute(Field.EXPONENT, expBegin, result.length());
\r
1428 // [Spark/CDL] Record the integer start index.
\r
1429 int intBegin = result.length();
\r
1430 // Record field information for caller.
\r
1431 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1432 fieldPosition.setBeginIndex(result.length());
\r
1433 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1434 fieldPosition.setBeginIndex(result.length());
\r
1438 int minSigDig = getMinimumSignificantDigits();
\r
1439 int maxSigDig = getMaximumSignificantDigits();
\r
1442 maxSigDig = Integer.MAX_VALUE;
\r
1445 // Output the integer portion. Here 'count' is the total number of integer
\r
1446 // digits we will display, including both leading zeros required to satisfy
\r
1447 // getMinimumIntegerDigits, and actual digits present in the number.
\r
1448 int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig;
\r
1449 if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
\r
1450 count = digitList.decimalAt;
\r
1453 // Handle the case where getMaximumIntegerDigits() is smaller than the real
\r
1454 // number of integer digits. If this is so, we output the least significant
\r
1455 // max integer digits. For example, the value 1997 printed with 2 max integer
\r
1456 // digits is just "97".
\r
1458 int digitIndex = 0; // Index into digitList.fDigits[]
\r
1459 if (count > maxIntDig && maxIntDig >= 0) {
\r
1460 count = maxIntDig;
\r
1461 digitIndex = digitList.decimalAt - count;
\r
1464 int sizeBeforeIntegerPart = result.length();
\r
1465 for (i = count - 1; i >= 0; --i) {
\r
1466 if (i < digitList.decimalAt && digitIndex < digitList.count
\r
1467 && sigCount < maxSigDig) {
\r
1468 // Output a real digit
\r
1469 byte d = digitList.digits[digitIndex++];
\r
1470 result.append((char) (d + zeroDelta));
\r
1473 // Output a zero (leading or trailing)
\r
1474 result.append(zero);
\r
1475 if (sigCount > 0) {
\r
1480 // Output grouping separator if necessary.
\r
1481 if (isGroupingPosition(i)) {
\r
1482 result.append(grouping);
\r
1483 // [Spark/CDL] Add grouping separator attribute here.
\r
1485 // Length of grouping separator is 1.
\r
1486 addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
\r
1491 // Record field information for caller.
\r
1492 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1493 fieldPosition.setEndIndex(result.length());
\r
1494 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1495 fieldPosition.setEndIndex(result.length());
\r
1498 // Determine whether or not there are any printable fractional digits. If
\r
1499 // we've used up the digits we know there aren't.
\r
1500 boolean fractionPresent = (!isInteger && digitIndex < digitList.count)
\r
1501 || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
\r
1503 // If there is no fraction present, and we haven't printed any integer digits,
\r
1504 // then print a zero. Otherwise we won't print _any_ digits, and we won't be
\r
1505 // able to parse this string.
\r
1506 if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
\r
1507 result.append(zero);
\r
1508 // [Spark/CDL] Add attribute for integer part.
\r
1510 addAttribute(Field.INTEGER, intBegin, result.length());
\r
1512 // Output the decimal separator if we always do so.
\r
1513 if (decimalSeparatorAlwaysShown || fractionPresent) {
\r
1514 result.append(decimal);
\r
1515 // [Spark/CDL] Add attribute for decimal separator
\r
1517 addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length());
\r
1521 // Record field information for caller.
\r
1522 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1523 fieldPosition.setBeginIndex(result.length());
\r
1524 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1525 fieldPosition.setBeginIndex(result.length());
\r
1528 // [Spark/CDL] Record the begin index of fraction part.
\r
1529 int fracBegin = result.length();
\r
1531 count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
\r
1532 if (useSigDig && (sigCount == maxSigDig ||
\r
1533 (sigCount >= minSigDig && digitIndex == digitList.count))) {
\r
1536 for (i = 0; i < count; ++i) {
\r
1537 // Here is where we escape from the loop. We escape if we've output the
\r
1538 // maximum fraction digits (specified in the for expression above). We
\r
1539 // also stop when we've output the minimum digits and either: we have an
\r
1540 // integer, so there is no fractional stuff to display, or we're out of
\r
1541 // significant digits.
\r
1542 if (!useSigDig && i >= getMinimumFractionDigits() &&
\r
1543 (isInteger || digitIndex >= digitList.count)) {
\r
1547 // Output leading fractional zeros. These are zeros that come after the
\r
1548 // decimal but before any significant digits. These are only output if
\r
1549 // abs(number being formatted) < 1.0.
\r
1550 if (-1 - i > (digitList.decimalAt - 1)) {
\r
1551 result.append(zero);
\r
1555 // Output a digit, if we have any precision left, or a zero if we
\r
1556 // don't. We don't want to output noise digits.
\r
1557 if (!isInteger && digitIndex < digitList.count) {
\r
1558 result.append((char) (digitList.digits[digitIndex++] + zeroDelta));
\r
1560 result.append(zero);
\r
1563 // If we reach the maximum number of significant digits, or if we output
\r
1564 // all the real digits and reach the minimum, then we are done.
\r
1566 if (useSigDig && (sigCount == maxSigDig ||
\r
1567 (digitIndex == digitList.count && sigCount >= minSigDig))) {
\r
1572 // Record field information for caller.
\r
1573 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1574 fieldPosition.setEndIndex(result.length());
\r
1575 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1576 fieldPosition.setEndIndex(result.length());
\r
1579 // [Spark/CDL] Add attribute information if necessary.
\r
1580 if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
\r
1581 addAttribute(Field.FRACTION, fracBegin, result.length());
\r
1585 int suffixLen = appendAffix(result, isNegative, false, parseAttr);
\r
1587 addPadding(result, fieldPosition, prefixLen, suffixLen);
\r
1591 private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen,
\r
1593 if (formatWidth > 0) {
\r
1594 int len = formatWidth - result.length();
\r
1596 char[] padding = new char[len];
\r
1597 for (int i = 0; i < len; ++i) {
\r
1600 switch (padPosition) {
\r
1601 case PAD_AFTER_PREFIX:
\r
1602 result.insert(prefixLen, padding);
\r
1604 case PAD_BEFORE_PREFIX:
\r
1605 result.insert(0, padding);
\r
1607 case PAD_BEFORE_SUFFIX:
\r
1608 result.insert(result.length() - suffixLen, padding);
\r
1610 case PAD_AFTER_SUFFIX:
\r
1611 result.append(padding);
\r
1614 if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) {
\r
1615 fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
\r
1616 fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
\r
1623 * Parses the given string, returning a <code>Number</code> object to represent the
\r
1624 * parsed value. <code>Double</code> objects are returned to represent non-integral
\r
1625 * values which cannot be stored in a <code>BigDecimal</code>. These are
\r
1626 * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is
\r
1627 * false (the default), all other values are returned as <code>Long</code>,
\r
1628 * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of
\r
1629 * preference. If {@link #isParseBigDecimal()} is true, all other values are returned
\r
1630 * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.
\r
1632 * @param text the string to be parsed
\r
1633 * @param parsePosition defines the position where parsing is to begin, and upon
\r
1634 * return, the position where parsing left off. If the position has not changed upon
\r
1635 * return, then parsing failed.
\r
1636 * @return a <code>Number</code> object with the parsed value or
\r
1637 * <code>null</code> if the parse failed
\r
1640 public Number parse(String text, ParsePosition parsePosition) {
\r
1641 return (Number) parse(text, parsePosition, false);
\r
1645 * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,
\r
1646 * this method will attempt to parse a generic currency name, searching for a match of
\r
1647 * this object's locale's currency display names, or for a 3-letter ISO currency
\r
1648 * code. This method will fail if this format is not a currency format, that is, if it
\r
1649 * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.
\r
1651 * @param text the string to parse
\r
1652 * @param pos input-output position; on input, the position within text to match; must
\r
1653 * have 0 <= pos.getIndex() < text.length(); on output, the position after the last
\r
1654 * matched character. If the parse fails, the position in unchanged upon output.
\r
1655 * @return a CurrencyAmount, or null upon failure
\r
1657 CurrencyAmount parseCurrency(String text, ParsePosition pos) {
\r
1658 return (CurrencyAmount) parse(text, pos, true);
\r
1662 * Parses the given text as either a Number or a CurrencyAmount.
\r
1664 * @param text the string to parse
\r
1665 * @param parsePosition input-output position; on input, the position within text to
\r
1666 * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after
\r
1667 * the last matched character. If the parse fails, the position in unchanged upon
\r
1669 * @param parseCurrency if true, a CurrencyAmount is parsed and returned; otherwise a
\r
1670 * Number is parsed and returned
\r
1671 * @return a Number or CurrencyAmount or null
\r
1673 private Object parse(String text, ParsePosition parsePosition, boolean parseCurrency) {
\r
1675 int i = backup = parsePosition.getIndex();
\r
1677 // Handle NaN as a special case:
\r
1679 // Skip padding characters, if around prefix
\r
1680 if (formatWidth > 0 &&
\r
1681 (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {
\r
1682 i = skipPadding(text, i);
\r
1684 if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) {
\r
1685 i += symbols.getNaN().length();
\r
1686 // Skip padding characters, if around suffix
\r
1687 if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
\r
1688 padPosition == PAD_AFTER_SUFFIX)) {
\r
1689 i = skipPadding(text, i);
\r
1691 parsePosition.setIndex(i);
\r
1692 return new Double(Double.NaN);
\r
1695 // NaN parse failed; start over
\r
1698 boolean[] status = new boolean[STATUS_LENGTH];
\r
1699 Currency[] currency = parseCurrency ? new Currency[1] : null;
\r
1700 if (currencySignCount > 0) {
\r
1701 if (!parseForCurrency(text, parsePosition, parseCurrency, currency, status)) {
\r
1705 if (!subparse(text, parsePosition, digitList, false, status, currency, negPrefixPattern,
\r
1706 negSuffixPattern, posPrefixPattern, posSuffixPattern,
\r
1707 Currency.SYMBOL_NAME)) {
\r
1708 parsePosition.setIndex(backup);
\r
1715 // Handle infinity
\r
1716 if (status[STATUS_INFINITE]) {
\r
1717 n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY :
\r
1718 Double.NEGATIVE_INFINITY);
\r
1721 // Handle underflow
\r
1722 else if (status[STATUS_UNDERFLOW]) {
\r
1723 n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
\r
1727 else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
\r
1728 n = new Double("-0.0");
\r
1732 // Do as much of the multiplier conversion as possible without
\r
1733 // losing accuracy.
\r
1734 int mult = multiplier; // Don't modify this.multiplier
\r
1735 while (mult % 10 == 0) {
\r
1736 --digitList.decimalAt;
\r
1740 // Handle integral values
\r
1741 if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
\r
1742 // hack quick long
\r
1743 if (digitList.decimalAt < 12) { // quick check for long
\r
1745 if (digitList.count > 0) {
\r
1747 while (nx < digitList.count) {
\r
1748 l = l * 10 + (char) digitList.digits[nx++] - '0';
\r
1750 while (nx++ < digitList.decimalAt) {
\r
1753 if (!status[STATUS_POSITIVE]) {
\r
1759 BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
\r
1760 n = (big.bitLength() < 64) ? (Number) new Long(big.longValue()) : (Number) big;
\r
1763 // Handle non-integral values or the case where parseBigDecimal is set
\r
1765 BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
\r
1768 n = big.divide(BigDecimal.valueOf(mult), mathContext);
\r
1773 // Assemble into CurrencyAmount if necessary
\r
1774 return parseCurrency ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n;
\r
1777 private boolean parseForCurrency(String text, ParsePosition parsePosition, boolean parseCurrency,
\r
1778 Currency[] currency, boolean[] status) {
\r
1779 int origPos = parsePosition.getIndex();
\r
1780 if (!isReadyForParsing) {
\r
1781 int savedCurrencySignCount = currencySignCount;
\r
1782 setupCurrencyAffixForAllPatterns();
\r
1783 // reset pattern back
\r
1784 if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
1785 applyPatternWithoutExpandAffix(formatPattern, false);
\r
1787 applyPattern(formatPattern, false);
\r
1789 isReadyForParsing = true;
\r
1791 int maxPosIndex = origPos;
\r
1792 int maxErrorPos = -1;
\r
1793 boolean[] savedStatus = null;
\r
1794 // First, parse against current pattern.
\r
1795 // Since current pattern could be set by applyPattern(),
\r
1796 // it could be an arbitrary pattern, and it may not be the one
\r
1797 // defined in current locale.
\r
1798 boolean[] tmpStatus = new boolean[STATUS_LENGTH];
\r
1799 ParsePosition tmpPos = new ParsePosition(origPos);
\r
1800 DigitList tmpDigitList = new DigitList();
\r
1802 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
1803 found = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,
\r
1804 negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
\r
1805 Currency.LONG_NAME);
\r
1807 found = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,
\r
1808 negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
\r
1809 Currency.SYMBOL_NAME);
\r
1812 if (tmpPos.getIndex() > maxPosIndex) {
\r
1813 maxPosIndex = tmpPos.getIndex();
\r
1814 savedStatus = tmpStatus;
\r
1815 digitList = tmpDigitList;
\r
1818 maxErrorPos = tmpPos.getErrorIndex();
\r
1820 // Then, parse against affix patterns. Those are currency patterns and currency
\r
1821 // plural patterns defined in the locale.
\r
1822 for (AffixForCurrency affix : affixPatternsForCurrency) {
\r
1823 tmpStatus = new boolean[STATUS_LENGTH];
\r
1824 tmpPos = new ParsePosition(origPos);
\r
1825 tmpDigitList = new DigitList();
\r
1826 boolean result = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,
\r
1827 affix.getNegPrefix(), affix.getNegSuffix(),
\r
1828 affix.getPosPrefix(), affix.getPosSuffix(),
\r
1829 affix.getPatternType());
\r
1832 if (tmpPos.getIndex() > maxPosIndex) {
\r
1833 maxPosIndex = tmpPos.getIndex();
\r
1834 savedStatus = tmpStatus;
\r
1835 digitList = tmpDigitList;
\r
1838 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex()
\r
1842 // Finally, parse against simple affix to find the match. For example, in
\r
1843 // TestMonster suite, if the to-be-parsed text is "-\u00A40,00".
\r
1844 // complexAffixCompare will not find match, since there is no ISO code matches
\r
1845 // "\u00A4", and the parse stops at "\u00A4". We will just use simple affix
\r
1846 // comparison (look for exact match) to pass it.
\r
1847 tmpStatus = new boolean[STATUS_LENGTH];
\r
1848 tmpPos = new ParsePosition(origPos);
\r
1849 tmpDigitList = new DigitList();
\r
1850 int savedCurrencySignCount = currencySignCount;
\r
1851 // set currencySignCount to 0 so that compareAffix function will fall to
\r
1852 // compareSimpleAffix path, not compareComplexAffix path.
\r
1853 currencySignCount = 0;
\r
1854 boolean result = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,
\r
1855 negativePrefix, negativeSuffix, positivePrefix, positiveSuffix,
\r
1856 Currency.SYMBOL_NAME);
\r
1857 currencySignCount = savedCurrencySignCount;
\r
1859 if (tmpPos.getIndex() > maxPosIndex) {
\r
1860 maxPosIndex = tmpPos.getIndex();
\r
1861 savedStatus = tmpStatus;
\r
1862 digitList = tmpDigitList;
\r
1866 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() :
\r
1871 // parsePosition.setIndex(origPos);
\r
1872 parsePosition.setErrorIndex(maxErrorPos);
\r
1874 parsePosition.setIndex(maxPosIndex);
\r
1875 parsePosition.setErrorIndex(-1);
\r
1876 for (int index = 0; index < STATUS_LENGTH; ++index) {
\r
1877 status[index] = savedStatus[index];
\r
1883 // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and
\r
1884 // currency plural pattern (CurrencyUnitPatterns).
\r
1885 private void setupCurrencyAffixForAllPatterns() {
\r
1886 if (currencyPluralInfo == null) {
\r
1887 currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
\r
1889 affixPatternsForCurrency = new HashSet<AffixForCurrency>();
\r
1891 // save the current pattern, since it will be changed by
\r
1892 // applyPatternWithoutExpandAffix
\r
1893 String savedFormatPattern = formatPattern;
\r
1895 // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so,
\r
1896 // only need to save one of them. Here, chose onlyApplyPatternWithoutExpandAffix
\r
1897 // without saving the actualy pattern in 'pattern' data member. TODO: is it uloc?
\r
1898 applyPatternWithoutExpandAffix(getPattern(symbols.getLocale(), NumberFormat.CURRENCYSTYLE),
\r
1900 AffixForCurrency affixes = new AffixForCurrency(
\r
1901 negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,
\r
1902 Currency.SYMBOL_NAME);
\r
1903 affixPatternsForCurrency.add(affixes);
\r
1905 // add plural pattern
\r
1906 Iterator<String> iter = currencyPluralInfo.pluralPatternIterator();
\r
1907 Set<String> currencyUnitPatternSet = new HashSet<String>();
\r
1908 while (iter.hasNext()) {
\r
1909 String pluralCount = iter.next();
\r
1910 String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
\r
1911 if (currencyPattern != null &&
\r
1912 currencyUnitPatternSet.contains(currencyPattern) == false) {
\r
1913 currencyUnitPatternSet.add(currencyPattern);
\r
1914 applyPatternWithoutExpandAffix(currencyPattern, false);
\r
1915 affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern,
\r
1916 posSuffixPattern, Currency.LONG_NAME);
\r
1917 affixPatternsForCurrency.add(affixes);
\r
1920 // reset pattern back
\r
1921 formatPattern = savedFormatPattern;
\r
1924 private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
\r
1925 private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
\r
1926 private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;
\r
1928 private static final int STATUS_INFINITE = 0;
\r
1929 private static final int STATUS_POSITIVE = 1;
\r
1930 private static final int STATUS_UNDERFLOW = 2;
\r
1931 private static final int STATUS_LENGTH = 3;
\r
1933 private static final UnicodeSet dotEquivalents = new UnicodeSet(
\r
1934 //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]"
\r
1941 0xFF61, 0xFF61).freeze();
\r
1943 private static final UnicodeSet commaEquivalents = new UnicodeSet(
\r
1944 //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]"
\r
1952 0xFF64, 0xFF64).freeze();
\r
1954 // private static final UnicodeSet otherGroupingSeparators = new UnicodeSet(
\r
1955 // //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
\r
1956 // 0x0020, 0x0020,
\r
1957 // 0x0027, 0x0027,
\r
1958 // 0x00A0, 0x00A0,
\r
1959 // 0x066C, 0x066C,
\r
1960 // 0x2000, 0x200A,
\r
1961 // 0x2018, 0x2019,
\r
1962 // 0x202F, 0x202F,
\r
1963 // 0x205F, 0x205F,
\r
1964 // 0x3000, 0x3000,
\r
1965 // 0xFF07, 0xFF07).freeze();
\r
1967 private static final UnicodeSet strictDotEquivalents = new UnicodeSet(
\r
1968 //"[.\u2024\uFE52\uFF0E\uFF61]"
\r
1973 0xFF61, 0xFF61).freeze();
\r
1975 private static final UnicodeSet strictCommaEquivalents = new UnicodeSet(
\r
1976 //"[,\u066B\uFE10\uFE50\uFF0C]"
\r
1981 0xFF0C, 0xFF0C).freeze();
\r
1983 // private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet(
\r
1984 // //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"
\r
1985 // 0x0020, 0x0020,
\r
1986 // 0x0027, 0x0027,
\r
1987 // 0x00A0, 0x00A0,
\r
1988 // 0x066C, 0x066C,
\r
1989 // 0x2000, 0x200A,
\r
1990 // 0x2018, 0x2019,
\r
1991 // 0x202F, 0x202F,
\r
1992 // 0x205F, 0x205F,
\r
1993 // 0x3000, 0x3000,
\r
1994 // 0xFF07, 0xFF07).freeze();
\r
1996 private static final UnicodeSet defaultGroupingSeparators =
\r
1997 // new UnicodeSet(dotEquivalents).addAll(commaEquivalents)
\r
1998 // .addAll(otherGroupingSeparators).freeze();
\r
2019 0xFF64, 0xFF64).freeze();
\r
2021 private static final UnicodeSet strictDefaultGroupingSeparators =
\r
2022 // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents)
\r
2023 // .addAll(strictOtherGroupingSeparators).freeze();
\r
2043 0xFF61, 0xFF61).freeze();
\r
2045 private static final UnicodeSet EMPTY_SET = new UnicodeSet().freeze();
\r
2047 // When parsing a number with big exponential value, it requires to transform the
\r
2048 // value into a string representation to construct BigInteger instance. We want to
\r
2049 // set the maximum size because it can easily trigger OutOfMemoryException.
\r
2050 // PARSE_MAX_EXPONENT is currently set to 1000, which is much bigger than MAX_VALUE of
\r
2051 // Double ( See the problem reported by ticket#5698
\r
2052 private static final int PARSE_MAX_EXPONENT = 1000;
\r
2055 * Parses the given text into a number. The text is parsed beginning at parsePosition,
\r
2056 * until an unparseable character is seen.
\r
2058 * @param text the string to parse.
\r
2059 * @param parsePosition the position at which to being parsing. Upon return, the first
\r
2060 * unparseable character.
\r
2061 * @param digits the DigitList to set to the parsed value.
\r
2062 * @param isExponent If true, parse an exponent. This means no infinite values and
\r
2064 * @param status Upon return contains boolean status flags indicating whether the
\r
2065 * value was infinite and whether it was positive.
\r
2066 * @param currency return value for parsed currency, for generic currency parsing
\r
2067 * mode, or null for normal parsing. In generic currency parsing mode, any currency is
\r
2068 * parsed, not just the currency that this formatter is set to.
\r
2069 * @param negPrefix negative prefix pattern
\r
2070 * @param negSuffix negative suffix pattern
\r
2071 * @param posPrefix positive prefix pattern
\r
2072 * @param negSuffix negative suffix pattern
\r
2073 * @param type type of currency to parse against, LONG_NAME only or not.
\r
2075 private final boolean subparse(
\r
2076 String text, ParsePosition parsePosition, DigitList digits, boolean isExponent,
\r
2077 boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix,
\r
2078 String posSuffix, int type) {
\r
2080 int position = parsePosition.getIndex();
\r
2081 int oldStart = parsePosition.getIndex();
\r
2083 // Match padding before prefix
\r
2084 if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
\r
2085 position = skipPadding(text, position);
\r
2088 // Match positive and negative prefixes; prefer longest match.
\r
2089 int posMatch = compareAffix(text, position, false, true, posPrefix, type, currency);
\r
2090 int negMatch = compareAffix(text, position, true, true, negPrefix, type, currency);
\r
2091 if (posMatch >= 0 && negMatch >= 0) {
\r
2092 if (posMatch > negMatch) {
\r
2094 } else if (negMatch > posMatch) {
\r
2098 if (posMatch >= 0) {
\r
2099 position += posMatch;
\r
2100 } else if (negMatch >= 0) {
\r
2101 position += negMatch;
\r
2103 parsePosition.setErrorIndex(position);
\r
2107 // Match padding after prefix
\r
2108 if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
\r
2109 position = skipPadding(text, position);
\r
2112 // process digits or Inf, find decimal position
\r
2113 status[STATUS_INFINITE] = false;
\r
2114 if (!isExponent && text.regionMatches(position, symbols.getInfinity(), 0,
\r
2115 symbols.getInfinity().length())) {
\r
2116 position += symbols.getInfinity().length();
\r
2117 status[STATUS_INFINITE] = true;
\r
2119 // We now have a string of digits, possibly with grouping symbols, and decimal
\r
2120 // points. We want to process these into a DigitList. We don't want to put a
\r
2121 // bunch of leading zeros into the DigitList though, so we keep track of the
\r
2122 // location of the decimal point, put only significant digits into the
\r
2123 // DigitList, and adjust the exponent as needed.
\r
2125 digits.decimalAt = digits.count = 0;
\r
2126 char zero = symbols.getZeroDigit();
\r
2127 char decimal = currencySignCount > 0 ? symbols.getMonetaryDecimalSeparator() : symbols
\r
2128 .getDecimalSeparator();
\r
2129 char grouping = symbols.getGroupingSeparator();
\r
2131 String exponentSep = symbols.getExponentSeparator();
\r
2132 boolean sawDecimal = false;
\r
2133 boolean sawGrouping = false;
\r
2134 boolean sawExponent = false;
\r
2135 boolean sawDigit = false;
\r
2136 long exponent = 0; // Set to the exponent value, if any
\r
2140 boolean strictParse = isParseStrict();
\r
2141 boolean strictFail = false; // did we exit with a strict parse failure?
\r
2142 int lastGroup = -1; // where did we last see a grouping separator?
\r
2143 int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
\r
2145 // Strict parsing leading zeroes. If a leading zero would be forced by the
\r
2146 // pattern, then don't fail strict parsing.
\r
2147 boolean strictLeadingZero = false;
\r
2148 int leadingZeroPos = 0;
\r
2149 int leadingZeroCount = 0;
\r
2151 // equivalent grouping and decimal support
\r
2152 boolean skipExtendedSeparatorParsing = ICUConfig.get(
\r
2153 "com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
\r
2156 UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? EMPTY_SET :
\r
2157 getEquivalentDecimals(decimal, strictParse);
\r
2158 UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? EMPTY_SET :
\r
2159 (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators);
\r
2161 // We have to track digitCount ourselves, because digits.count will pin when
\r
2162 // the maximum allowable digits is reached.
\r
2163 int digitCount = 0;
\r
2166 for (; position < text.length(); ++position) {
\r
2167 char ch = text.charAt(position);
\r
2170 // We recognize all digit ranges, not only the Latin digit range
\r
2171 // '0'..'9'. We do so by using the UCharacter.digit() method, which
\r
2172 // converts a valid Unicode digit to the range 0..9.
\r
2174 // The character 'ch' may be a digit. If so, place its value from 0 to 9
\r
2175 // in 'digit'. First try using the locale digit, which may or MAY NOT be a
\r
2176 // standard Unicode digit range. If this fails, try using the standard
\r
2177 // Unicode digit ranges by calling UCharacter.digit(). If this also fails,
\r
2178 // digit will have a value outside the range 0..9.
\r
2179 digit = ch - zero;
\r
2180 if (digit < 0 || digit > 9)
\r
2181 digit = UCharacter.digit(ch, 10);
\r
2184 // Cancel out backup setting (see grouping handler below)
\r
2185 if (strictParse && backup != -1) {
\r
2186 // comma followed by digit, so group before comma is a secondary
\r
2187 // group. If there was a group separator before that, the group
\r
2188 // must == the secondary group length, else it can be <= the the
\r
2189 // secondary group length.
\r
2190 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2)
\r
2191 || (lastGroup == -1 && position - oldStart - 1 > gs2)) {
\r
2192 strictFail = true;
\r
2195 lastGroup = backup;
\r
2197 backup = -1; // Do this BEFORE continue statement below!!!
\r
2200 // Handle leading zeros
\r
2201 if (digits.count == 0) {
\r
2202 if (!sawDecimal) {
\r
2203 if (strictParse && !isExponent) {
\r
2204 // Allow leading zeros in exponents
\r
2205 // Count leading zeros for checking later
\r
2206 if (!strictLeadingZero)
\r
2207 leadingZeroPos = position + 1;
\r
2208 strictLeadingZero = true;
\r
2209 ++leadingZeroCount;
\r
2211 // Ignore leading zeros in integer part of number.
\r
2215 // If we have seen the decimal, but no significant digits yet,
\r
2216 // then we account for leading zeros by decrementing the
\r
2217 // digits.decimalAt into negative values.
\r
2218 --digits.decimalAt;
\r
2221 digits.append((char) (digit + '0'));
\r
2223 } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
\r
2225 if (strictParse) {
\r
2226 if (backup != -1) {
\r
2227 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2)
\r
2228 || (lastGroup == -1 && position - oldStart - 1 > gs2)) {
\r
2229 strictFail = true;
\r
2232 lastGroup = backup;
\r
2238 digits.append((char) (digit + '0'));
\r
2240 // Cancel out backup setting (see grouping handler below)
\r
2242 } else if (!isExponent && ch == decimal) {
\r
2243 if (strictParse) {
\r
2244 if (backup != -1 ||
\r
2245 (lastGroup != -1 && position - lastGroup != groupingSize + 1)) {
\r
2246 strictFail = true;
\r
2250 // If we're only parsing integers, or if we ALREADY saw the decimal,
\r
2251 // then don't parse this one.
\r
2252 if (isParseIntegerOnly() || sawDecimal) {
\r
2255 digits.decimalAt = digitCount; // Not digits.count!
\r
2256 sawDecimal = true;
\r
2257 } else if (!isExponent && isGroupingUsed() && ch == grouping) {
\r
2261 if (strictParse) {
\r
2262 if ((!sawDigit || backup != -1)) {
\r
2263 // leading group, or two group separators in a row
\r
2264 strictFail = true;
\r
2268 // Ignore grouping characters, if we are using them, but require that
\r
2269 // they be followed by a digit. Otherwise we backup and reprocess
\r
2271 backup = position;
\r
2272 sawGrouping = true;
\r
2273 } else if (!isExponent && !sawDecimal && decimalEquiv.contains(ch)) {
\r
2274 if (strictParse) {
\r
2275 if (backup != -1 ||
\r
2276 (lastGroup != -1 && position - lastGroup != groupingSize + 1)) {
\r
2277 strictFail = true;
\r
2281 // If we're only parsing integers, then don't parse this one.
\r
2282 if (isParseIntegerOnly())
\r
2284 digits.decimalAt = digitCount; // Not digits.count!
\r
2286 // Once we see a decimal separator character, we only accept that
\r
2287 // decimal separator character from then on.
\r
2289 sawDecimal = true;
\r
2290 } else if (!isExponent && isGroupingUsed() && !sawGrouping &&
\r
2291 groupEquiv.contains(ch)) {
\r
2295 if (strictParse) {
\r
2296 if ((!sawDigit || backup != -1)) {
\r
2297 // leading group, or two group separators in a row
\r
2298 strictFail = true;
\r
2302 // Once we see a grouping character, we only accept that grouping
\r
2303 // character from then on.
\r
2306 // Ignore grouping characters, if we are using them, but require that
\r
2307 // they be followed by a digit. Otherwise we backup and reprocess
\r
2309 backup = position;
\r
2310 sawGrouping = true;
\r
2311 } else if (!isExponent && !sawExponent
\r
2312 && text.regionMatches(position, exponentSep, 0, exponentSep.length())) {
\r
2313 // Parse sign, if present
\r
2314 boolean negExp = false;
\r
2315 int pos = position + exponentSep.length();
\r
2316 if (pos < text.length()) {
\r
2317 ch = text.charAt(pos);
\r
2318 if (ch == symbols.getPlusSign()) {
\r
2320 } else if (ch == symbols.getMinusSign()) {
\r
2326 DigitList exponentDigits = new DigitList();
\r
2327 exponentDigits.count = 0;
\r
2328 while (pos < text.length()) {
\r
2329 digit = text.charAt(pos) - zero;
\r
2330 if (digit < 0 || digit > 9) {
\r
2331 // Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
\r
2332 // Should update reassign the value of 'ch' in the code: digit
\r
2333 // = Character.digit(ch, 10); [Richard/GCL]
\r
2334 digit = UCharacter.digit(text.charAt(pos), 10);
\r
2336 if (digit >= 0 && digit <= 9) {
\r
2337 exponentDigits.append((char) (digit + '0'));
\r
2344 if (exponentDigits.count > 0) {
\r
2345 // defer strict parse until we know we have a bona-fide exponent
\r
2346 if (strictParse) {
\r
2347 if (backup != -1 || lastGroup != -1) {
\r
2348 strictFail = true;
\r
2353 // Quick overflow check for exponential part. Actual limit check
\r
2354 // will be done later in this code.
\r
2355 if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
\r
2357 // set underflow flag
\r
2358 status[STATUS_UNDERFLOW] = true;
\r
2360 // set infinite flag
\r
2361 status[STATUS_INFINITE] = true;
\r
2364 exponentDigits.decimalAt = exponentDigits.count;
\r
2365 exponent = exponentDigits.getLong();
\r
2367 exponent = -exponent;
\r
2370 position = pos; // Advance past the exponent
\r
2371 sawExponent = true;
\r
2374 break; // Whether we fail or succeed, we exit this loop
\r
2381 position = backup;
\r
2383 // If there was no decimal point we have an integer
\r
2385 digits.decimalAt = digitCount; // Not digits.count!
\r
2387 // check for strict parse errors
\r
2388 if (strictParse && strictLeadingZero) {
\r
2389 if ((leadingZeroCount + digits.decimalAt) > this.getMinimumIntegerDigits()) {
\r
2390 parsePosition.setIndex(oldStart);
\r
2391 parsePosition.setErrorIndex(leadingZeroPos);
\r
2395 if (strictParse && !sawDecimal) {
\r
2396 if (lastGroup != -1 && position - lastGroup != groupingSize + 1) {
\r
2397 strictFail = true;
\r
2401 // only set with strictParse and a leading zero error leading zeros are an
\r
2402 // error with strict parsing except immediately before nondigit (except
\r
2403 // group separator followed by digit), or end of text.
\r
2405 parsePosition.setIndex(oldStart);
\r
2406 parsePosition.setErrorIndex(position);
\r
2410 // Adjust for exponent, if any
\r
2411 exponent += digits.decimalAt;
\r
2412 if (exponent < -PARSE_MAX_EXPONENT) {
\r
2413 status[STATUS_UNDERFLOW] = true;
\r
2414 } else if (exponent > PARSE_MAX_EXPONENT) {
\r
2415 status[STATUS_INFINITE] = true;
\r
2417 digits.decimalAt = (int) exponent;
\r
2420 // If none of the text string was recognized. For example, parse "x" with
\r
2421 // pattern "#0.00" (return index and error index both 0) parse "$" with
\r
2422 // pattern "$#0.00". (return index 0 and error index 1).
\r
2423 if (!sawDigit && digitCount == 0) {
\r
2424 parsePosition.setIndex(oldStart);
\r
2425 parsePosition.setErrorIndex(oldStart);
\r
2430 // Match padding before suffix
\r
2431 if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
\r
2432 position = skipPadding(text, position);
\r
2435 // Match positive and negative suffixes; prefer longest match.
\r
2436 if (posMatch >= 0) {
\r
2437 posMatch = compareAffix(text, position, false, false, posSuffix, type, currency);
\r
2439 if (negMatch >= 0) {
\r
2440 negMatch = compareAffix(text, position, true, false, negSuffix, type, currency);
\r
2442 if (posMatch >= 0 && negMatch >= 0) {
\r
2443 if (posMatch > negMatch) {
\r
2445 } else if (negMatch > posMatch) {
\r
2450 // Fail if neither or both
\r
2451 if ((posMatch >= 0) == (negMatch >= 0)) {
\r
2452 parsePosition.setErrorIndex(position);
\r
2456 position += (posMatch >= 0 ? posMatch : negMatch);
\r
2458 // Match padding after suffix
\r
2459 if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
\r
2460 position = skipPadding(text, position);
\r
2463 parsePosition.setIndex(position);
\r
2465 status[STATUS_POSITIVE] = (posMatch >= 0);
\r
2467 if (parsePosition.getIndex() == oldStart) {
\r
2468 parsePosition.setErrorIndex(position);
\r
2475 * Returns a set of characters equivalent to the given desimal separator used for
\r
2476 * parsing number. This method may return an empty set.
\r
2478 private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) {
\r
2479 UnicodeSet equivSet = EMPTY_SET;
\r
2480 if (strictParse) {
\r
2481 if (strictDotEquivalents.contains(decimal)) {
\r
2482 equivSet = strictDotEquivalents;
\r
2483 } else if (strictCommaEquivalents.contains(decimal)) {
\r
2484 equivSet = strictCommaEquivalents;
\r
2487 if (dotEquivalents.contains(decimal)) {
\r
2488 equivSet = dotEquivalents;
\r
2489 } else if (commaEquivalents.contains(decimal)) {
\r
2490 equivSet = commaEquivalents;
\r
2497 * Starting at position, advance past a run of pad characters, if any. Return the
\r
2498 * index of the first character after position that is not a pad character. Result is
\r
2501 private final int skipPadding(String text, int position) {
\r
2502 while (position < text.length() && text.charAt(position) == pad) {
\r
2509 * Returns the length matched by the given affix, or -1 if none. Runs of white space
\r
2510 * in the affix, match runs of white space in the input. Pattern white space and input
\r
2511 * white space are determined differently; see code.
\r
2513 * @param text input text
\r
2514 * @param pos offset into input at which to begin matching
\r
2515 * @param isNegative
\r
2517 * @param affixPat affix pattern used for currency affix comparison
\r
2518 * @param type compare against currency type, LONG_NAME only or not.
\r
2519 * @param currency return value for parsed currency, for generic currency parsing
\r
2520 * mode, or null for normal parsing. In generic currency parsing mode, any currency
\r
2521 * is parsed, not just the currency that this formatter is set to.
\r
2522 * @return length of input that matches, or -1 if match failure
\r
2524 private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix,
\r
2525 String affixPat, int type, Currency[] currency) {
\r
2526 if (currency != null || currencyChoice != null || currencySignCount > 0) {
\r
2527 return compareComplexAffix(affixPat, text, pos, type, currency);
\r
2530 return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos);
\r
2532 return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos);
\r
2538 * Return the length matched by the given affix, or -1 if none. Runs of white space in
\r
2539 * the affix, match runs of white space in the input. Pattern white space and input
\r
2540 * white space are determined differently; see code.
\r
2542 * @param affix pattern string, taken as a literal
\r
2543 * @param input input text
\r
2544 * @param pos offset into input at which to begin matching
\r
2545 * @return length of input that matches, or -1 if match failure
\r
2547 private static int compareSimpleAffix(String affix, String input, int pos) {
\r
2549 for (int i = 0; i < affix.length();) {
\r
2550 int c = UTF16.charAt(affix, i);
\r
2551 int len = UTF16.getCharCount(c);
\r
2552 if (UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2553 // We may have a pattern like: \u200F and input text like: \u200F Note
\r
2554 // that U+200F and U+0020 are RuleWhiteSpace but only U+0020 is
\r
2555 // UWhiteSpace. So we have to first do a direct match of the run of RULE
\r
2556 // whitespace in the pattern, then match any extra characters.
\r
2557 boolean literalMatch = false;
\r
2558 while (pos < input.length() && UTF16.charAt(input, pos) == c) {
\r
2559 literalMatch = true;
\r
2562 if (i == affix.length()) {
\r
2565 c = UTF16.charAt(affix, i);
\r
2566 len = UTF16.getCharCount(c);
\r
2567 if (!UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2572 // Advance over run in affix
\r
2573 i = skipRuleWhiteSpace(affix, i);
\r
2575 // Advance over run in input text. Must see at least one white space char
\r
2576 // in input, unless we've already matched some characters literally.
\r
2578 pos = skipUWhiteSpace(input, pos);
\r
2579 if (pos == s && !literalMatch) {
\r
2582 // If we skip UWhiteSpace in the input text, we need to skip it in the
\r
2583 // pattern. Otherwise, the previous lines may have skipped over text
\r
2584 // (such as U+00A0) that is also in the affix.
\r
2585 i = skipUWhiteSpace(affix, i);
\r
2587 if (pos < input.length() && UTF16.charAt(input, pos) == c) {
\r
2595 return pos - start;
\r
2599 * Skips over a run of zero or more isRuleWhiteSpace() characters at pos in text.
\r
2601 private static int skipRuleWhiteSpace(String text, int pos) {
\r
2602 while (pos < text.length()) {
\r
2603 int c = UTF16.charAt(text, pos);
\r
2604 if (!UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2607 pos += UTF16.getCharCount(c);
\r
2613 * Skips over a run of zero or more isUWhiteSpace() characters at pos in text.
\r
2615 private static int skipUWhiteSpace(String text, int pos) {
\r
2616 while (pos < text.length()) {
\r
2617 int c = UTF16.charAt(text, pos);
\r
2618 if (!UCharacter.isUWhiteSpace(c)) {
\r
2621 pos += UTF16.getCharCount(c);
\r
2627 * Returns the length matched by the given affix, or -1 if none.
\r
2629 * @param affixPat pattern string
\r
2630 * @param text input text
\r
2631 * @param pos offset into input at which to begin matching
\r
2632 * @param type parse against currency type, LONG_NAME only or not.
\r
2633 * @param currency return value for parsed currency, for generic
\r
2634 * currency parsing mode, or null for normal parsing. In generic
\r
2635 * currency parsing mode, any currency is parsed, not just the
\r
2636 * currency that this formatter is set to.
\r
2637 * @return position after the matched text, or -1 if match failure
\r
2639 private int compareComplexAffix(String affixPat, String text, int pos, int type,
\r
2640 Currency[] currency) {
\r
2642 for (int i = 0; i < affixPat.length() && pos >= 0;) {
\r
2643 char c = affixPat.charAt(i++);
\r
2646 int j = affixPat.indexOf(QUOTE, i);
\r
2648 pos = match(text, pos, QUOTE);
\r
2651 } else if (j > i) {
\r
2652 pos = match(text, pos, affixPat.substring(i, j));
\r
2654 if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) {
\r
2655 pos = match(text, pos, QUOTE);
\r
2662 // Unterminated quote; should be caught by apply
\r
2664 throw new RuntimeException();
\r
2671 case CURRENCY_SIGN:
\r
2672 // since the currency names in choice format is saved the same way as
\r
2673 // other currency names, do not need to do currency choice parsing here.
\r
2674 // the general currency parsing parse against all names, including names
\r
2675 // in choice format. assert(currency != null || (getCurrency() != null &&
\r
2676 // currencyChoice != null));
\r
2677 boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
\r
2681 boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;
\r
2686 // Parse generic currency -- anything for which we have a display name, or
\r
2687 // any 3-letter ISO code. Try to parse display name for our locale; first
\r
2688 // determine our locale. TODO: use locale in CurrencyPluralInfo
\r
2689 ULocale uloc = getLocale(ULocale.VALID_LOCALE);
\r
2690 if (uloc == null) {
\r
2691 // applyPattern has been called; use the symbols
\r
2692 uloc = symbols.getLocale(ULocale.VALID_LOCALE);
\r
2694 // Delegate parse of display name => ISO code to Currency
\r
2695 ParsePosition ppos = new ParsePosition(pos);
\r
2696 // using Currency.parse to handle mixed style parsing.
\r
2697 String iso = Currency.parse(uloc, text, type, ppos);
\r
2699 // If parse succeeds, populate currency[0]
\r
2700 if (iso != null) {
\r
2701 if (currency != null) {
\r
2702 currency[0] = Currency.getInstance(iso);
\r
2704 pos = ppos.getIndex();
\r
2709 case PATTERN_PERCENT:
\r
2710 c = symbols.getPercent();
\r
2712 case PATTERN_PER_MILLE:
\r
2713 c = symbols.getPerMill();
\r
2715 case PATTERN_MINUS:
\r
2716 c = symbols.getMinusSign();
\r
2719 pos = match(text, pos, c);
\r
2720 if (UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2721 i = skipRuleWhiteSpace(affixPat, i);
\r
2725 return pos - start;
\r
2729 * Matches a single character at text[pos] and return the index of the next character
\r
2730 * upon success. Return -1 on failure. If isRuleWhiteSpace(ch) then match a run of
\r
2731 * white space in text.
\r
2733 static final int match(String text, int pos, int ch) {
\r
2734 if (pos >= text.length()) {
\r
2737 if (UCharacterProperty.isRuleWhiteSpace(ch)) {
\r
2738 // Advance over run of white space in input text
\r
2739 // Must see at least one white space char in input
\r
2741 pos = skipRuleWhiteSpace(text, pos);
\r
2747 return (pos >= 0 && UTF16.charAt(text, pos) == ch) ? (pos + UTF16.getCharCount(ch)) : -1;
\r
2751 * Matches a string at text[pos] and return the index of the next character upon
\r
2752 * success. Return -1 on failure. Match a run of white space in str with a run of
\r
2753 * white space in text.
\r
2755 static final int match(String text, int pos, String str) {
\r
2756 for (int i = 0; i < str.length() && pos >= 0;) {
\r
2757 int ch = UTF16.charAt(str, i);
\r
2758 i += UTF16.getCharCount(ch);
\r
2759 pos = match(text, pos, ch);
\r
2760 if (UCharacterProperty.isRuleWhiteSpace(ch)) {
\r
2761 i = skipRuleWhiteSpace(str, i);
\r
2768 * Returns a copy of the decimal format symbols used by this format.
\r
2770 * @return desired DecimalFormatSymbols
\r
2771 * @see DecimalFormatSymbols
\r
2774 public DecimalFormatSymbols getDecimalFormatSymbols() {
\r
2776 // don't allow multiple references
\r
2777 return (DecimalFormatSymbols) symbols.clone();
\r
2778 } catch (Exception foo) {
\r
2779 return null; // should never happen
\r
2784 * Sets the decimal format symbols used by this format. The format uses a copy of the
\r
2785 * provided symbols.
\r
2787 * @param newSymbols desired DecimalFormatSymbols
\r
2788 * @see DecimalFormatSymbols
\r
2791 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
\r
2792 symbols = (DecimalFormatSymbols) newSymbols.clone();
\r
2793 setCurrencyForSymbols();
\r
2794 expandAffixes(null);
\r
2798 * Update the currency object to match the symbols. This method is used only when the
\r
2799 * caller has passed in a symbols object that may not be the default object for its
\r
2802 private void setCurrencyForSymbols() {
\r
2804 // Bug 4212072 Update the affix strings according to symbols in order to keep the
\r
2805 // affix strings up to date. [Richard/GCL]
\r
2807 // With the introduction of the Currency object, the currency symbols in the DFS
\r
2808 // object are ignored. For backward compatibility, we check any explicitly set DFS
\r
2809 // object. If it is a default symbols object for its locale, we change the
\r
2810 // currency object to one for that locale. If it is custom, we set the currency to
\r
2812 DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getLocale());
\r
2814 if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())
\r
2815 && symbols.getInternationalCurrencySymbol()
\r
2816 .equals(def.getInternationalCurrencySymbol())) {
\r
2817 setCurrency(Currency.getInstance(symbols.getLocale()));
\r
2819 setCurrency(null);
\r
2824 * Returns the positive prefix.
\r
2826 * <p>Examples: +123, $123, sFr123
\r
2827 * @return the prefix
\r
2830 public String getPositivePrefix() {
\r
2831 return positivePrefix;
\r
2835 * Sets the positive prefix.
\r
2837 * <p>Examples: +123, $123, sFr123
\r
2838 * @param newValue the prefix
\r
2841 public void setPositivePrefix(String newValue) {
\r
2842 positivePrefix = newValue;
\r
2843 posPrefixPattern = null;
\r
2847 * Returns the negative prefix.
\r
2849 * <p>Examples: -123, ($123) (with negative suffix), sFr-123
\r
2851 * @return the prefix
\r
2854 public String getNegativePrefix() {
\r
2855 return negativePrefix;
\r
2859 * Sets the negative prefix.
\r
2861 * <p>Examples: -123, ($123) (with negative suffix), sFr-123
\r
2862 * @param newValue the prefix
\r
2865 public void setNegativePrefix(String newValue) {
\r
2866 negativePrefix = newValue;
\r
2867 negPrefixPattern = null;
\r
2871 * Returns the positive suffix.
\r
2873 * <p>Example: 123%
\r
2875 * @return the suffix
\r
2878 public String getPositiveSuffix() {
\r
2879 return positiveSuffix;
\r
2883 * Sets the positive suffix.
\r
2885 * <p>Example: 123%
\r
2886 * @param newValue the suffix
\r
2889 public void setPositiveSuffix(String newValue) {
\r
2890 positiveSuffix = newValue;
\r
2891 posSuffixPattern = null;
\r
2895 * Returns the negative suffix.
\r
2897 * <p>Examples: -123%, ($123) (with positive suffixes)
\r
2899 * @return the suffix
\r
2902 public String getNegativeSuffix() {
\r
2903 return negativeSuffix;
\r
2907 * Sets the positive suffix.
\r
2909 * <p>Examples: 123%
\r
2910 * @param newValue the suffix
\r
2913 public void setNegativeSuffix(String newValue) {
\r
2914 negativeSuffix = newValue;
\r
2915 negSuffixPattern = null;
\r
2919 * Returns the multiplier for use in percent, permill, etc. For a percentage, set the
\r
2920 * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
\r
2921 * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
\r
2924 * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
\r
2926 * @return the multiplier
\r
2929 public int getMultiplier() {
\r
2930 return multiplier;
\r
2934 * Sets the multiplier for use in percent, permill, etc. For a percentage, set the
\r
2935 * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent
\r
2936 * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be
\r
2939 * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
\r
2941 * @param newValue the multiplier
\r
2944 public void setMultiplier(int newValue) {
\r
2945 if (newValue == 0) {
\r
2946 throw new IllegalArgumentException("Bad multiplier: " + newValue);
\r
2948 multiplier = newValue;
\r
2952 * {@icu} Returns the rounding increment.
\r
2954 * @return A positive rounding increment, or <code>null</code> if rounding is not in
\r
2956 * @see #setRoundingIncrement
\r
2957 * @see #getRoundingMode
\r
2958 * @see #setRoundingMode
\r
2961 public java.math.BigDecimal getRoundingIncrement() {
\r
2962 if (roundingIncrementICU == null)
\r
2964 return roundingIncrementICU.toBigDecimal();
\r
2968 * {@icu} Sets the rounding increment. This method also controls whether rounding is
\r
2971 * @param newValue A positive rounding increment, or <code>null</code> or
\r
2972 * <code>BigDecimal(0.0)</code> to disable rounding.
\r
2973 * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
\r
2974 * @see #getRoundingIncrement
\r
2975 * @see #getRoundingMode
\r
2976 * @see #setRoundingMode
\r
2979 public void setRoundingIncrement(java.math.BigDecimal newValue) {
\r
2980 if (newValue == null) {
\r
2981 setRoundingIncrement((BigDecimal) null);
\r
2983 setRoundingIncrement(new BigDecimal(newValue));
\r
2988 * {@icu} Sets the rounding increment. This method also controls whether rounding is
\r
2991 * @param newValue A positive rounding increment, or <code>null</code> or
\r
2992 * <code>BigDecimal(0.0)</code> to disable rounding.
\r
2993 * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
\r
2994 * @see #getRoundingIncrement
\r
2995 * @see #getRoundingMode
\r
2996 * @see #setRoundingMode
\r
2999 public void setRoundingIncrement(BigDecimal newValue) {
\r
3000 int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO);
\r
3002 throw new IllegalArgumentException("Illegal rounding increment");
\r
3005 setInternalRoundingIncrement(null);
\r
3007 setInternalRoundingIncrement(newValue);
\r
3009 setRoundingDouble();
\r
3013 * {@icu} Sets the rounding increment. This method also controls whether rounding is
\r
3016 * @param newValue A positive rounding increment, or 0.0 to disable rounding.
\r
3017 * @throws IllegalArgumentException if <code>newValue</code> is < 0.0
\r
3018 * @see #getRoundingIncrement
\r
3019 * @see #getRoundingMode
\r
3020 * @see #setRoundingMode
\r
3023 public void setRoundingIncrement(double newValue) {
\r
3024 if (newValue < 0.0) {
\r
3025 throw new IllegalArgumentException("Illegal rounding increment");
\r
3027 roundingDouble = newValue;
\r
3028 roundingDoubleReciprocal = 0.0d;
\r
3029 if (newValue == 0.0d) {
\r
3030 setRoundingIncrement((BigDecimal) null);
\r
3032 roundingDouble = newValue;
\r
3033 if (roundingDouble < 1.0d) {
\r
3034 double rawRoundedReciprocal = 1.0d / roundingDouble;
\r
3035 setRoundingDoubleReciprocal(rawRoundedReciprocal);
\r
3037 setInternalRoundingIncrement(new BigDecimal(newValue));
\r
3041 private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {
\r
3042 roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
\r
3043 if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
\r
3044 roundingDoubleReciprocal = 0.0d;
\r
3048 static final double roundingIncrementEpsilon = 0.000000001;
\r
3051 * Returns the rounding mode.
\r
3053 * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
\r
3054 * <code>BigDecimal.ROUND_UNNECESSARY</code>.
\r
3055 * @see #setRoundingIncrement
\r
3056 * @see #getRoundingIncrement
\r
3057 * @see #setRoundingMode
\r
3058 * @see java.math.BigDecimal
\r
3061 public int getRoundingMode() {
\r
3062 return roundingMode;
\r
3066 * Sets the rounding mode. This has no effect unless the rounding increment is greater
\r
3069 * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
\r
3070 * <code>BigDecimal.ROUND_UNNECESSARY</code>.
\r
3071 * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
\r
3072 * @see #setRoundingIncrement
\r
3073 * @see #getRoundingIncrement
\r
3074 * @see #getRoundingMode
\r
3075 * @see java.math.BigDecimal
\r
3078 public void setRoundingMode(int roundingMode) {
\r
3079 if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
\r
3080 throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);
\r
3083 this.roundingMode = roundingMode;
\r
3085 if (getRoundingIncrement() == null) {
\r
3086 setRoundingIncrement(Math.pow(10.0, (double) -getMaximumFractionDigits()));
\r
3091 * Returns the width to which the output of <code>format()</code> is padded. The width is
\r
3092 * counted in 16-bit code units.
\r
3094 * @return the format width, or zero if no padding is in effect
\r
3095 * @see #setFormatWidth
\r
3096 * @see #getPadCharacter
\r
3097 * @see #setPadCharacter
\r
3098 * @see #getPadPosition
\r
3099 * @see #setPadPosition
\r
3102 public int getFormatWidth() {
\r
3103 return formatWidth;
\r
3107 * Sets the width to which the output of <code>format()</code> is
\r
3108 * padded. The width is counted in 16-bit code units. This method
\r
3109 * also controls whether padding is enabled.
\r
3111 * @param width the width to which to pad the result of
\r
3112 * <code>format()</code>, or zero to disable padding
\r
3113 * @exception IllegalArgumentException if <code>width</code> is < 0
\r
3114 * @see #getFormatWidth
\r
3115 * @see #getPadCharacter
\r
3116 * @see #setPadCharacter
\r
3117 * @see #getPadPosition
\r
3118 * @see #setPadPosition
\r
3121 public void setFormatWidth(int width) {
\r
3123 throw new IllegalArgumentException("Illegal format width");
\r
3125 formatWidth = width;
\r
3129 * {@icu} Returns the character used to pad to the format width. The default is ' '.
\r
3131 * @return the pad character
\r
3132 * @see #setFormatWidth
\r
3133 * @see #getFormatWidth
\r
3134 * @see #setPadCharacter
\r
3135 * @see #getPadPosition
\r
3136 * @see #setPadPosition
\r
3139 public char getPadCharacter() {
\r
3144 * {@icu} Sets the character used to pad to the format width. If padding is not
\r
3145 * enabled, then this will take effect if padding is later enabled.
\r
3147 * @param padChar the pad character
\r
3148 * @see #setFormatWidth
\r
3149 * @see #getFormatWidth
\r
3150 * @see #getPadCharacter
\r
3151 * @see #getPadPosition
\r
3152 * @see #setPadPosition
\r
3155 public void setPadCharacter(char padChar) {
\r
3160 * {@icu} Returns the position at which padding will take place. This is the location at
\r
3161 * which padding will be inserted if the result of <code>format()</code> is shorter
\r
3162 * than the format width.
\r
3164 * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
\r
3165 * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
\r
3166 * <code>PAD_AFTER_SUFFIX</code>.
\r
3167 * @see #setFormatWidth
\r
3168 * @see #getFormatWidth
\r
3169 * @see #setPadCharacter
\r
3170 * @see #getPadCharacter
\r
3171 * @see #setPadPosition
\r
3172 * @see #PAD_BEFORE_PREFIX
\r
3173 * @see #PAD_AFTER_PREFIX
\r
3174 * @see #PAD_BEFORE_SUFFIX
\r
3175 * @see #PAD_AFTER_SUFFIX
\r
3178 public int getPadPosition() {
\r
3179 return padPosition;
\r
3183 * {@icu} Sets the position at which padding will take place. This is the location at
\r
3184 * which padding will be inserted if the result of <code>format()</code> is shorter
\r
3185 * than the format width. This has no effect unless padding is enabled.
\r
3187 * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
\r
3188 * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
\r
3189 * <code>PAD_AFTER_SUFFIX</code>.
\r
3190 * @exception IllegalArgumentException if the pad position in unrecognized
\r
3191 * @see #setFormatWidth
\r
3192 * @see #getFormatWidth
\r
3193 * @see #setPadCharacter
\r
3194 * @see #getPadCharacter
\r
3195 * @see #getPadPosition
\r
3196 * @see #PAD_BEFORE_PREFIX
\r
3197 * @see #PAD_AFTER_PREFIX
\r
3198 * @see #PAD_BEFORE_SUFFIX
\r
3199 * @see #PAD_AFTER_SUFFIX
\r
3202 public void setPadPosition(int padPos) {
\r
3203 if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
\r
3204 throw new IllegalArgumentException("Illegal pad position");
\r
3206 padPosition = padPos;
\r
3210 * {@icu} Returns whether or not scientific notation is used.
\r
3212 * @return true if this object formats and parses scientific notation
\r
3213 * @see #setScientificNotation
\r
3214 * @see #getMinimumExponentDigits
\r
3215 * @see #setMinimumExponentDigits
\r
3216 * @see #isExponentSignAlwaysShown
\r
3217 * @see #setExponentSignAlwaysShown
\r
3220 public boolean isScientificNotation() {
\r
3221 return useExponentialNotation;
\r
3225 * {@icu} Sets whether or not scientific notation is used. When scientific notation is
\r
3226 * used, the effective maximum number of integer digits is <= 8. If the maximum number
\r
3227 * of integer digits is set to more than 8, the effective maximum will be 1. This
\r
3228 * allows this call to generate a 'default' scientific number format without
\r
3229 * additional changes.
\r
3231 * @param useScientific true if this object formats and parses scientific notation
\r
3232 * @see #isScientificNotation
\r
3233 * @see #getMinimumExponentDigits
\r
3234 * @see #setMinimumExponentDigits
\r
3235 * @see #isExponentSignAlwaysShown
\r
3236 * @see #setExponentSignAlwaysShown
\r
3239 public void setScientificNotation(boolean useScientific) {
\r
3240 useExponentialNotation = useScientific;
\r
3244 * {@icu} Returns the minimum exponent digits that will be shown.
\r
3246 * @return the minimum exponent digits that will be shown
\r
3247 * @see #setScientificNotation
\r
3248 * @see #isScientificNotation
\r
3249 * @see #setMinimumExponentDigits
\r
3250 * @see #isExponentSignAlwaysShown
\r
3251 * @see #setExponentSignAlwaysShown
\r
3254 public byte getMinimumExponentDigits() {
\r
3255 return minExponentDigits;
\r
3259 * {@icu} Sets the minimum exponent digits that will be shown. This has no effect
\r
3260 * unless scientific notation is in use.
\r
3262 * @param minExpDig a value >= 1 indicating the fewest exponent
\r
3263 * digits that will be shown
\r
3264 * @exception IllegalArgumentException if <code>minExpDig</code> < 1
\r
3265 * @see #setScientificNotation
\r
3266 * @see #isScientificNotation
\r
3267 * @see #getMinimumExponentDigits
\r
3268 * @see #isExponentSignAlwaysShown
\r
3269 * @see #setExponentSignAlwaysShown
\r
3272 public void setMinimumExponentDigits(byte minExpDig) {
\r
3273 if (minExpDig < 1) {
\r
3274 throw new IllegalArgumentException("Exponent digits must be >= 1");
\r
3276 minExponentDigits = minExpDig;
\r
3280 * {@icu} Returns whether the exponent sign is always shown.
\r
3282 * @return true if the exponent is always prefixed with either the localized minus
\r
3283 * sign or the localized plus sign, false if only negative exponents are prefixed with
\r
3284 * the localized minus sign.
\r
3285 * @see #setScientificNotation
\r
3286 * @see #isScientificNotation
\r
3287 * @see #setMinimumExponentDigits
\r
3288 * @see #getMinimumExponentDigits
\r
3289 * @see #setExponentSignAlwaysShown
\r
3292 public boolean isExponentSignAlwaysShown() {
\r
3293 return exponentSignAlwaysShown;
\r
3297 * {@icu} Sets whether the exponent sign is always shown. This has no effect unless
\r
3298 * scientific notation is in use.
\r
3300 * @param expSignAlways true if the exponent is always prefixed with either the
\r
3301 * localized minus sign or the localized plus sign, false if only negative exponents
\r
3302 * are prefixed with the localized minus sign.
\r
3303 * @see #setScientificNotation
\r
3304 * @see #isScientificNotation
\r
3305 * @see #setMinimumExponentDigits
\r
3306 * @see #getMinimumExponentDigits
\r
3307 * @see #isExponentSignAlwaysShown
\r
3310 public void setExponentSignAlwaysShown(boolean expSignAlways) {
\r
3311 exponentSignAlwaysShown = expSignAlways;
\r
3315 * Returns the grouping size. Grouping size is the number of digits between grouping
\r
3316 * separators in the integer portion of a number. For example, in the number
\r
3317 * "123,456.78", the grouping size is 3.
\r
3319 * @see #setGroupingSize
\r
3320 * @see NumberFormat#isGroupingUsed
\r
3321 * @see DecimalFormatSymbols#getGroupingSeparator
\r
3324 public int getGroupingSize() {
\r
3325 return groupingSize;
\r
3329 * Sets the grouping size. Grouping size is the number of digits between grouping
\r
3330 * separators in the integer portion of a number. For example, in the number
\r
3331 * "123,456.78", the grouping size is 3.
\r
3333 * @see #getGroupingSize
\r
3334 * @see NumberFormat#setGroupingUsed
\r
3335 * @see DecimalFormatSymbols#setGroupingSeparator
\r
3338 public void setGroupingSize(int newValue) {
\r
3339 groupingSize = (byte) newValue;
\r
3343 * {@icu} Returns the secondary grouping size. In some locales one grouping interval
\r
3344 * is used for the least significant integer digits (the primary grouping size), and
\r
3345 * another is used for all others (the secondary grouping size). A formatter
\r
3346 * supporting a secondary grouping size will return a positive integer unequal to the
\r
3347 * primary grouping size returned by <code>getGroupingSize()</code>. For example, if
\r
3348 * the primary grouping size is 4, and the secondary grouping size is 2, then the
\r
3349 * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".
\r
3351 * @return the secondary grouping size, or a value less than one if there is none
\r
3352 * @see #setSecondaryGroupingSize
\r
3353 * @see NumberFormat#isGroupingUsed
\r
3354 * @see DecimalFormatSymbols#getGroupingSeparator
\r
3357 public int getSecondaryGroupingSize() {
\r
3358 return groupingSize2;
\r
3362 * {@icu} Sets the secondary grouping size. If set to a value less than 1, then
\r
3363 * secondary grouping is turned off, and the primary grouping size is used for all
\r
3364 * intervals, not just the least significant.
\r
3366 * @see #getSecondaryGroupingSize
\r
3367 * @see NumberFormat#setGroupingUsed
\r
3368 * @see DecimalFormatSymbols#setGroupingSeparator
\r
3371 public void setSecondaryGroupingSize(int newValue) {
\r
3372 groupingSize2 = (byte) newValue;
\r
3376 * {@icu} Returns the MathContext used by this format.
\r
3378 * @return desired MathContext
\r
3379 * @see #getMathContext
\r
3382 public MathContext getMathContextICU() {
\r
3383 return mathContext;
\r
3387 * {@icu} Returns the MathContext used by this format.
\r
3389 * @return desired MathContext
\r
3390 * @see #getMathContext
\r
3393 public java.math.MathContext getMathContext() {
\r
3395 // don't allow multiple references
\r
3396 return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(),
\r
3397 java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
\r
3398 } catch (Exception foo) {
\r
3399 return null; // should never happen
\r
3404 * {@icu} Sets the MathContext used by this format.
\r
3406 * @param newValue desired MathContext
\r
3407 * @see #getMathContext
\r
3410 public void setMathContextICU(MathContext newValue) {
\r
3411 mathContext = newValue;
\r
3415 * {@icu} Sets the MathContext used by this format.
\r
3417 * @param newValue desired MathContext
\r
3418 * @see #getMathContext
\r
3421 public void setMathContext(java.math.MathContext newValue) {
\r
3422 mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false,
\r
3423 (newValue.getRoundingMode()).ordinal());
\r
3427 * Returns the behavior of the decimal separator with integers. (The decimal
\r
3428 * separator will always appear with decimals.) <p> Example: Decimal ON: 12345 ->
\r
3429 * 12345.; OFF: 12345 -> 12345
\r
3433 public boolean isDecimalSeparatorAlwaysShown() {
\r
3434 return decimalSeparatorAlwaysShown;
\r
3438 * Sets the behavior of the decimal separator with integers. (The decimal separator
\r
3439 * will always appear with decimals.)
\r
3441 * <p>This only affects formatting, and only where there might be no digits after the
\r
3442 * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This
\r
3443 * is independent of parsing. If you want parsing to stop at the decimal point, use
\r
3444 * setParseIntegerOnly.
\r
3447 * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
\r
3451 public void setDecimalSeparatorAlwaysShown(boolean newValue) {
\r
3452 decimalSeparatorAlwaysShown = newValue;
\r
3456 * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might
\r
3457 * return null if the decimal format is not a plural type currency decimal
\r
3458 * format. Plural type currency decimal format means either the pattern in the decimal
\r
3459 * format contains 3 currency signs, or the decimal format is initialized with
\r
3460 * PLURALCURRENCYSTYLE.
\r
3462 * @return desired CurrencyPluralInfo
\r
3463 * @see CurrencyPluralInfo
\r
3466 public CurrencyPluralInfo getCurrencyPluralInfo() {
\r
3468 // don't allow multiple references
\r
3469 return currencyPluralInfo == null ? null :
\r
3470 (CurrencyPluralInfo) currencyPluralInfo.clone();
\r
3471 } catch (Exception foo) {
\r
3472 return null; // should never happen
\r
3477 * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of
\r
3478 * the provided information.
\r
3480 * @param newInfo desired CurrencyPluralInfo
\r
3481 * @see CurrencyPluralInfo
\r
3484 public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
\r
3485 currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
\r
3486 isReadyForParsing = false;
\r
3490 * Overrides clone.
\r
3493 public Object clone() {
\r
3495 DecimalFormat other = (DecimalFormat) super.clone();
\r
3496 other.symbols = (DecimalFormatSymbols) symbols.clone();
\r
3497 other.digitList = new DigitList(); // fix for JB#5358
\r
3498 if (currencyPluralInfo != null) {
\r
3499 other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
\r
3502 // TODO: We need to figure out whether we share a single copy of DigitList by
\r
3503 // multiple cloned copies. format/subformat are designed to use a single
\r
3504 // instance, but parse/subparse implementation is not.
\r
3506 } catch (Exception e) {
\r
3507 throw new IllegalStateException();
\r
3512 * Overrides equals.
\r
3515 public boolean equals(Object obj) {
\r
3518 if (!super.equals(obj))
\r
3519 return false; // super does class check
\r
3521 DecimalFormat other = (DecimalFormat) obj;
\r
3522 // Add the comparison of the four new added fields ,they are posPrefixPattern,
\r
3523 // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL]
\r
3524 // following are added to accomodate changes for currency plural format.
\r
3525 return currencySignCount == other.currencySignCount
\r
3526 && (style != NumberFormat.PLURALCURRENCYSTYLE ||
\r
3527 equals(posPrefixPattern, other.posPrefixPattern)
\r
3528 && equals(posSuffixPattern, other.posSuffixPattern)
\r
3529 && equals(negPrefixPattern, other.negPrefixPattern)
\r
3530 && equals(negSuffixPattern, other.negSuffixPattern))
\r
3531 && multiplier == other.multiplier
\r
3532 && groupingSize == other.groupingSize
\r
3533 && groupingSize2 == other.groupingSize2
\r
3534 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
\r
3535 && useExponentialNotation == other.useExponentialNotation
\r
3536 && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)
\r
3537 && useSignificantDigits == other.useSignificantDigits
\r
3538 && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits
\r
3539 && maxSignificantDigits == other.maxSignificantDigits)
\r
3540 && symbols.equals(other.symbols)
\r
3541 && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);
\r
3544 // method to unquote the strings and compare
\r
3545 private boolean equals(String pat1, String pat2) {
\r
3546 if (pat1 == null || pat2 == null) {
\r
3547 return (pat1 == null && pat2 == null);
\r
3550 if (pat1.equals(pat2)) {
\r
3553 return unquote(pat1).equals(unquote(pat2));
\r
3556 private String unquote(String pat) {
\r
3557 StringBuilder buf = new StringBuilder(pat.length());
\r
3559 while (i < pat.length()) {
\r
3560 char ch = pat.charAt(i++);
\r
3561 if (ch != QUOTE) {
\r
3565 return buf.toString();
\r
3568 // protected void handleToString(StringBuffer buf) {
\r
3569 // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
\r
3570 // buf.append("positivePrefix: '" + positivePrefix + "'\n");
\r
3571 // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
\r
3572 // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
\r
3573 // buf.append("negPrefixPattern: '" +
\r
3574 // com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
\r
3575 // buf.append("negativePrefix: '" +
\r
3576 // com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
\r
3577 // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
\r
3578 // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
\r
3579 // buf.append("multiplier: '" + multiplier + "'\n");
\r
3580 // buf.append("groupingSize: '" + groupingSize + "'\n");
\r
3581 // buf.append("groupingSize2: '" + groupingSize2 + "'\n");
\r
3582 // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
\r
3583 // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
\r
3584 // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
\r
3585 // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
\r
3586 // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
\r
3587 // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
\r
3588 // buf.append("symbols: '" + symbols + "'");
\r
3592 * Overrides hashCode.
\r
3595 public int hashCode() {
\r
3596 return super.hashCode() * 37 + positivePrefix.hashCode();
\r
3597 // just enough fields for a reasonable distribution
\r
3601 * Synthesizes a pattern string that represents the current state of this Format
\r
3604 * @see #applyPattern
\r
3607 public String toPattern() {
\r
3608 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
3609 // the prefix or suffix pattern might not be defined yet, so they can not be
\r
3610 // synthesized, instead, get them directly. but it might not be the actual
\r
3611 // pattern used in formatting. the actual pattern used in formatting depends
\r
3612 // on the formatted number's plural count.
\r
3613 return formatPattern;
\r
3615 return toPattern(false);
\r
3619 * Synthesizes a localized pattern string that represents the current state of this
\r
3622 * @see #applyPattern
\r
3625 public String toLocalizedPattern() {
\r
3626 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
3627 return formatPattern;
\r
3629 return toPattern(true);
\r
3633 * Expands the affix pattern strings into the expanded affix strings. If any affix
\r
3634 * pattern string is null, do not expand it. This method should be called any time the
\r
3635 * symbols or the affix patterns change in order to keep the expanded affix strings up
\r
3636 * to date. This method also will be called before formatting if format currency
\r
3637 * plural names, since the plural name is not a static one, it is based on the
\r
3638 * currency plural count, the affix will be known only after the currency plural count
\r
3639 * is know. In which case, the parameter 'pluralCount' will be a non-null currency
\r
3640 * plural count. In all other cases, the 'pluralCount' is null, which means it is not
\r
3643 // Bug 4212072 [Richard/GCL]
\r
3644 private void expandAffixes(String pluralCount) {
\r
3645 // expandAffix() will set currencyChoice to a non-null value if
\r
3646 // appropriate AND if it is null.
\r
3647 currencyChoice = null;
\r
3649 // Reuse one StringBuffer for better performance
\r
3650 StringBuffer buffer = new StringBuffer();
\r
3651 if (posPrefixPattern != null) {
\r
3652 expandAffix(posPrefixPattern, pluralCount, buffer, false);
\r
3653 positivePrefix = buffer.toString();
\r
3655 if (posSuffixPattern != null) {
\r
3656 expandAffix(posSuffixPattern, pluralCount, buffer, false);
\r
3657 positiveSuffix = buffer.toString();
\r
3659 if (negPrefixPattern != null) {
\r
3660 expandAffix(negPrefixPattern, pluralCount, buffer, false);
\r
3661 negativePrefix = buffer.toString();
\r
3663 if (negSuffixPattern != null) {
\r
3664 expandAffix(negSuffixPattern, pluralCount, buffer, false);
\r
3665 negativeSuffix = buffer.toString();
\r
3670 * Expands an affix pattern into an affix string. All characters in the pattern are
\r
3671 * literal unless bracketed by QUOTEs. The following characters outside QUOTE are
\r
3672 * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
\r
3673 * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international
\r
3674 * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural
\r
3675 * long names, such as "US Dollars". Any other character outside QUOTE represents
\r
3676 * itself. Quoted text must be well-formed.
\r
3678 * This method is used in two distinct ways. First, it is used to expand the stored
\r
3679 * affix patterns into actual affixes. For this usage, doFormat must be false. Second,
\r
3680 * it is used to expand the stored affix patterns given a specific number (doFormat ==
\r
3681 * true), for those rare cases in which a currency format references a ChoiceFormat
\r
3682 * (e.g., en_IN display name for INR). The number itself is taken from digitList.
\r
3684 * When used in the first way, this method has a side effect: It sets currencyChoice
\r
3685 * to a ChoiceFormat object, if the currency's display name in this locale is a
\r
3686 * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to
\r
3689 * @param pattern the non-null, possibly empty pattern
\r
3690 * @param pluralCount the plural count. It is only used for currency plural format. In
\r
3691 * which case, it is the plural count of the currency amount. For example, in en_US,
\r
3692 * it is the singular "one", or the plural "other". For all other cases, it is null,
\r
3693 * and is not being used.
\r
3694 * @param buffer a scratch StringBuffer; its contents will be lost
\r
3695 * @param doFormat if false, then the pattern will be expanded, and if a currency
\r
3696 * symbol is encountered that expands to a ChoiceFormat, the currencyChoice member
\r
3697 * variable will be initialized if it is null. If doFormat is true, then it is assumed
\r
3698 * that the currencyChoice has been created, and it will be used to format the value
\r
3701 // Bug 4212072 [Richard/GCL]
\r
3702 private void expandAffix(String pattern, String pluralCount, StringBuffer buffer,
\r
3703 boolean doFormat) {
\r
3704 buffer.setLength(0);
\r
3705 for (int i = 0; i < pattern.length();) {
\r
3706 char c = pattern.charAt(i++);
\r
3709 int j = pattern.indexOf(QUOTE, i);
\r
3711 buffer.append(QUOTE);
\r
3714 } else if (j > i) {
\r
3715 buffer.append(pattern.substring(i, j));
\r
3717 if (i < pattern.length() && pattern.charAt(i) == QUOTE) {
\r
3718 buffer.append(QUOTE);
\r
3725 // Unterminated quote; should be caught by apply
\r
3727 throw new RuntimeException();
\r
3734 case CURRENCY_SIGN:
\r
3735 // As of ICU 2.2 we use the currency object, and ignore the currency
\r
3736 // symbols in the DFS, unless we have a null currency object. This occurs
\r
3737 // if resurrecting a pre-2.2 object or if the user sets a custom DFS.
\r
3738 boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN;
\r
3739 boolean plural = false;
\r
3742 if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) {
\r
3749 Currency currency = getCurrency();
\r
3750 if (currency != null) {
\r
3751 // plural name is only needed when pluralCount != null, which means
\r
3752 // when formatting currency plural names. For other cases,
\r
3753 // pluralCount == null, and plural names are not needed.
\r
3754 if (plural && pluralCount != null) {
\r
3755 boolean isChoiceFormat[] = new boolean[1];
\r
3756 s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,
\r
3757 pluralCount, isChoiceFormat);
\r
3758 } else if (!intl) {
\r
3759 boolean isChoiceFormat[] = new boolean[1];
\r
3760 s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME,
\r
3762 if (isChoiceFormat[0]) {
\r
3763 // Two modes here: If doFormat is false, we set up
\r
3764 // currencyChoice. If doFormat is true, we use the previously
\r
3765 // created currencyChoice to format the value in digitList.
\r
3767 // If the currency is handled by a ChoiceFormat, then
\r
3768 // we're not going to use the expanded
\r
3769 // patterns. Instantiate the ChoiceFormat and return.
\r
3770 if (currencyChoice == null) {
\r
3771 currencyChoice = new ChoiceFormat(s);
\r
3773 // We could almost return null or "" here, since the
\r
3774 // expanded affixes are almost not used at all in this
\r
3775 // situation. However, one method -- toPattern() -- still
\r
3776 // does use the expanded affixes, in order to set up a
\r
3777 // padding pattern. We use the CURRENCY_SIGN as a
\r
3779 s = String.valueOf(CURRENCY_SIGN);
\r
3781 FieldPosition pos = new FieldPosition(0); // ignored
\r
3782 currencyChoice.format(digitList.getDouble(), buffer, pos);
\r
3787 s = currency.getCurrencyCode();
\r
3790 s = intl ? symbols.getInternationalCurrencySymbol() :
\r
3791 symbols.getCurrencySymbol();
\r
3795 case PATTERN_PERCENT:
\r
3796 c = symbols.getPercent();
\r
3798 case PATTERN_PER_MILLE:
\r
3799 c = symbols.getPerMill();
\r
3801 case PATTERN_MINUS:
\r
3802 c = symbols.getMinusSign();
\r
3810 * Append an affix to the given StringBuffer.
\r
3813 * buffer to append to
\r
3814 * @param isNegative
\r
3817 private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,
\r
3818 boolean parseAttr) {
\r
3819 if (currencyChoice != null) {
\r
3820 String affixPat = null;
\r
3822 affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
\r
3824 affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
\r
3826 StringBuffer affixBuf = new StringBuffer();
\r
3827 expandAffix(affixPat, null, affixBuf, true);
\r
3828 buf.append(affixBuf);
\r
3829 return affixBuf.length();
\r
3832 String affix = null;
\r
3834 affix = isNegative ? negativePrefix : positivePrefix;
\r
3836 affix = isNegative ? negativeSuffix : positiveSuffix;
\r
3838 // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
\r
3840 int offset = affix.indexOf(symbols.getCurrencySymbol());
\r
3841 if (-1 == offset) {
\r
3842 offset = affix.indexOf(symbols.getPercent());
\r
3843 if (-1 == offset) {
\r
3847 formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length());
\r
3849 buf.append(affix);
\r
3850 return affix.length();
\r
3854 * [Spark/CDL] This is a newly added method, used to add attributes for prefix and
\r
3857 private void formatAffix2Attribute(String affix, int begin, int end) {
\r
3858 // [Spark/CDL] It is the invoker's responsibility to ensure that, before the
\r
3859 // invocation of this method, attributes is not null. if( attributes == null )
\r
3861 if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
\r
3862 addAttribute(Field.CURRENCY, begin, end);
\r
3863 } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
\r
3864 addAttribute(Field.SIGN, begin, end);
\r
3865 } else if (affix.indexOf(symbols.getPercent()) > -1) {
\r
3866 addAttribute(Field.PERCENT, begin, end);
\r
3867 } else if (affix.indexOf(symbols.getPerMill()) > -1) {
\r
3868 addAttribute(Field.PERMILLE, begin, end);
\r
3873 * [Spark/CDL] Use this method to add attribute.
\r
3875 private void addAttribute(Field field, int begin, int end) {
\r
3876 FieldPosition pos = new FieldPosition(field);
\r
3877 pos.setBeginIndex(begin);
\r
3878 pos.setEndIndex(end);
\r
3879 attributes.add(pos);
\r
3883 * Formats the object to an attributed string, and return the corresponding iterator.
\r
3887 public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
\r
3888 if (!(obj instanceof Number))
\r
3889 throw new IllegalArgumentException();
\r
3890 Number number = (Number) obj;
\r
3891 StringBuffer text = null;
\r
3892 attributes.clear();
\r
3893 if (obj instanceof BigInteger) {
\r
3894 text = format((BigInteger) number, new StringBuffer(), new FieldPosition(0), true);
\r
3895 } else if (obj instanceof java.math.BigDecimal) {
\r
3896 text = format((java.math.BigDecimal) number, new StringBuffer(), new FieldPosition(0)
\r
3898 } else if (obj instanceof Double) {
\r
3899 text = format(number.doubleValue(), new StringBuffer(), new FieldPosition(0), true);
\r
3900 } else if (obj instanceof Integer || obj instanceof Long) {
\r
3901 text = format(number.longValue(), new StringBuffer(), new FieldPosition(0), true);
\r
3904 AttributedString as = new AttributedString(text.toString());
\r
3906 // add NumberFormat field attributes to the AttributedString
\r
3907 for (int i = 0; i < attributes.size(); i++) {
\r
3908 FieldPosition pos = attributes.get(i);
\r
3909 Format.Field attribute = pos.getFieldAttribute();
\r
3910 as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());
\r
3913 // return the CharacterIterator from AttributedString
\r
3914 return as.getIterator();
\r
3918 * Appends an affix pattern to the given StringBuffer. Localize unquoted specials.
\r
3920 private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,
\r
3921 boolean localized) {
\r
3922 String affixPat = null;
\r
3924 affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
\r
3926 affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
\r
3929 // When there is a null affix pattern, we use the affix itself.
\r
3930 if (affixPat == null) {
\r
3931 String affix = null;
\r
3933 affix = isNegative ? negativePrefix : positivePrefix;
\r
3935 affix = isNegative ? negativeSuffix : positiveSuffix;
\r
3937 // Do this crudely for now: Wrap everything in quotes.
\r
3938 buffer.append(QUOTE);
\r
3939 for (int i = 0; i < affix.length(); ++i) {
\r
3940 char ch = affix.charAt(i);
\r
3941 if (ch == QUOTE) {
\r
3942 buffer.append(ch);
\r
3944 buffer.append(ch);
\r
3946 buffer.append(QUOTE);
\r
3951 buffer.append(affixPat);
\r
3954 for (i = 0; i < affixPat.length(); ++i) {
\r
3955 char ch = affixPat.charAt(i);
\r
3958 j = affixPat.indexOf(QUOTE, i + 1);
\r
3960 throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
\r
3962 buffer.append(affixPat.substring(i, j + 1));
\r
3965 case PATTERN_PER_MILLE:
\r
3966 ch = symbols.getPerMill();
\r
3968 case PATTERN_PERCENT:
\r
3969 ch = symbols.getPercent();
\r
3971 case PATTERN_MINUS:
\r
3972 ch = symbols.getMinusSign();
\r
3975 // check if char is same as any other symbol
\r
3976 if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) {
\r
3977 buffer.append(QUOTE);
\r
3978 buffer.append(ch);
\r
3979 buffer.append(QUOTE);
\r
3981 buffer.append(ch);
\r
3988 * Does the real work of generating a pattern.
\r
3990 private String toPattern(boolean localized) {
\r
3991 StringBuffer result = new StringBuffer();
\r
3992 char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
\r
3993 char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
\r
3994 char sigDigit = 0;
\r
3995 boolean useSigDig = areSignificantDigitsUsed();
\r
3997 sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
\r
3999 char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR;
\r
4001 int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
\r
4002 String roundingDigits = null;
\r
4003 int padPos = (formatWidth > 0) ? padPosition : -1;
\r
4004 String padSpec = (formatWidth > 0)
\r
4005 ? new StringBuffer(2).append(localized
\r
4006 ? symbols.getPadEscape()
\r
4007 : PATTERN_PAD_ESCAPE).append(pad).toString()
\r
4009 if (roundingIncrementICU != null) {
\r
4010 i = roundingIncrementICU.scale();
\r
4011 roundingDigits = roundingIncrementICU.movePointRight(i).toString();
\r
4012 roundingDecimalPos = roundingDigits.length() - i;
\r
4014 for (int part = 0; part < 2; ++part) {
\r
4015 // variable not used int partStart = result.length();
\r
4016 if (padPos == PAD_BEFORE_PREFIX) {
\r
4017 result.append(padSpec);
\r
4020 // Use original symbols read from resources in pattern eg. use "\u00A4"
\r
4021 // instead of "$" in Locale.US [Richard/GCL]
\r
4022 appendAffixPattern(result, part != 0, true, localized);
\r
4023 if (padPos == PAD_AFTER_PREFIX) {
\r
4024 result.append(padSpec);
\r
4026 int sub0Start = result.length();
\r
4027 int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
\r
4028 if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
\r
4029 g += groupingSize2;
\r
4031 int maxDig = 0, minDig = 0, maxSigDig = 0;
\r
4033 minDig = getMinimumSignificantDigits();
\r
4034 maxDig = maxSigDig = getMaximumSignificantDigits();
\r
4036 minDig = getMinimumIntegerDigits();
\r
4037 maxDig = getMaximumIntegerDigits();
\r
4039 if (useExponentialNotation) {
\r
4040 if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
\r
4043 } else if (useSigDig) {
\r
4044 maxDig = Math.max(maxDig, g + 1);
\r
4046 maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1;
\r
4048 for (i = maxDig; i > 0; --i) {
\r
4049 if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) {
\r
4050 result.append(group);
\r
4053 // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos,
\r
4054 // count from the right) Use # if pos > maxSigDig or 1 <= pos <=
\r
4055 // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <=
\r
4057 result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
\r
4059 if (roundingDigits != null) {
\r
4060 int pos = roundingDecimalPos - i;
\r
4061 if (pos >= 0 && pos < roundingDigits.length()) {
\r
4062 result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
\r
4066 result.append(i <= minDig ? zero : digit);
\r
4070 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
\r
4071 result.append(localized ? symbols.getDecimalSeparator() :
\r
4072 PATTERN_DECIMAL_SEPARATOR);
\r
4074 int pos = roundingDecimalPos;
\r
4075 for (i = 0; i < getMaximumFractionDigits(); ++i) {
\r
4076 if (roundingDigits != null && pos < roundingDigits.length()) {
\r
4077 result.append(pos < 0 ? zero :
\r
4078 (char) (roundingDigits.charAt(pos) - '0' + zero));
\r
4082 result.append(i < getMinimumFractionDigits() ? zero : digit);
\r
4085 if (useExponentialNotation) {
\r
4087 result.append(symbols.getExponentSeparator());
\r
4089 result.append(PATTERN_EXPONENT);
\r
4091 if (exponentSignAlwaysShown) {
\r
4092 result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN);
\r
4094 for (i = 0; i < minExponentDigits; ++i) {
\r
4095 result.append(zero);
\r
4098 if (padSpec != null && !useExponentialNotation) {
\r
4099 int add = formatWidth
\r
4103 ? positivePrefix.length() + positiveSuffix.length()
\r
4104 : negativePrefix.length() + negativeSuffix.length());
\r
4106 result.insert(sub0Start, digit);
\r
4109 // Only add a grouping separator if we have at least 2 additional
\r
4110 // characters to be added, so we don't end up with ",###".
\r
4111 if (add > 1 && isGroupingPosition(maxDig)) {
\r
4112 result.insert(sub0Start, group);
\r
4117 if (padPos == PAD_BEFORE_SUFFIX) {
\r
4118 result.append(padSpec);
\r
4120 // Use original symbols read from resources in pattern eg. use "\u00A4"
\r
4121 // instead of "$" in Locale.US [Richard/GCL]
\r
4122 appendAffixPattern(result, part != 0, false, localized);
\r
4123 if (padPos == PAD_AFTER_SUFFIX) {
\r
4124 result.append(padSpec);
\r
4127 if (negativeSuffix.equals(positiveSuffix) &&
\r
4128 negativePrefix.equals(PATTERN_MINUS + positivePrefix)) {
\r
4131 result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);
\r
4135 return result.toString();
\r
4139 * Applies the given pattern to this Format object. A pattern is a short-hand
\r
4140 * specification for the various formatting properties. These properties can also be
\r
4141 * changed individually through the various setter methods.
\r
4143 * <p>There is no limit to integer digits are set by this routine, since that is the
\r
4144 * typical end-user desire; use setMaximumInteger if you want to set a real value. For
\r
4145 * negative numbers, use a second pattern, separated by a semicolon
\r
4147 * <p>Example "#,#00.0#" -> 1,234.56
\r
4149 * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
\r
4150 * fraction digits.
\r
4152 * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
\r
4154 * <p>In negative patterns, the minimum and maximum counts are ignored; these are
\r
4155 * presumed to be set in the positive pattern.
\r
4159 public void applyPattern(String pattern) {
\r
4160 applyPattern(pattern, false);
\r
4164 * Applies the given pattern to this Format object. The pattern is assumed to be in a
\r
4165 * localized notation. A pattern is a short-hand specification for the various
\r
4166 * formatting properties. These properties can also be changed individually through
\r
4167 * the various setter methods.
\r
4169 * <p>There is no limit to integer digits are set by this routine, since that is the
\r
4170 * typical end-user desire; use setMaximumInteger if you want to set a real value. For
\r
4171 * negative numbers, use a second pattern, separated by a semicolon
\r
4173 * <p>Example "#,#00.0#" -> 1,234.56
\r
4175 * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
\r
4176 * fraction digits.
\r
4178 * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
\r
4180 * <p>In negative patterns, the minimum and maximum counts are ignored; these are
\r
4181 * presumed to be set in the positive pattern.
\r
4185 public void applyLocalizedPattern(String pattern) {
\r
4186 applyPattern(pattern, true);
\r
4190 * Does the real work of applying a pattern.
\r
4192 private void applyPattern(String pattern, boolean localized) {
\r
4193 applyPatternWithoutExpandAffix(pattern, localized);
\r
4194 expandAffixAdjustWidth(null);
\r
4197 private void expandAffixAdjustWidth(String pluralCount) {
\r
4198 // Bug 4212072 Update the affix strings according to symbols in order to keep the
\r
4199 // affix strings up to date. [Richard/GCL]
\r
4200 expandAffixes(pluralCount);
\r
4202 // Now that we have the actual prefix and suffix, fix up formatWidth
\r
4203 if (formatWidth > 0) {
\r
4204 formatWidth += positivePrefix.length() + positiveSuffix.length();
\r
4208 private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
\r
4209 char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
\r
4210 char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
\r
4211 char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
\r
4212 char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
\r
4213 char percent = PATTERN_PERCENT;
\r
4214 char perMill = PATTERN_PER_MILLE;
\r
4215 char digit = PATTERN_DIGIT; // '#'
\r
4216 char separator = PATTERN_SEPARATOR;
\r
4217 String exponent = String.valueOf(PATTERN_EXPONENT);
\r
4218 char plus = PATTERN_PLUS_SIGN;
\r
4219 char padEscape = PATTERN_PAD_ESCAPE;
\r
4220 char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL]
\r
4222 zeroDigit = symbols.getZeroDigit();
\r
4223 sigDigit = symbols.getSignificantDigit();
\r
4224 groupingSeparator = symbols.getGroupingSeparator();
\r
4225 decimalSeparator = symbols.getDecimalSeparator();
\r
4226 percent = symbols.getPercent();
\r
4227 perMill = symbols.getPerMill();
\r
4228 digit = symbols.getDigit();
\r
4229 separator = symbols.getPatternSeparator();
\r
4230 exponent = symbols.getExponentSeparator();
\r
4231 plus = symbols.getPlusSign();
\r
4232 padEscape = symbols.getPadEscape();
\r
4233 minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL]
\r
4235 char nineDigit = (char) (zeroDigit + 9);
\r
4237 boolean gotNegative = false;
\r
4240 // Part 0 is the positive pattern. Part 1, if present, is the negative
\r
4242 for (int part = 0; part < 2 && pos < pattern.length(); ++part) {
\r
4243 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,
\r
4244 // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and
\r
4245 // suffix, and consists of pattern characters. In the prefix and suffix,
\r
4246 // percent, permille, and currency symbols are recognized and translated.
\r
4247 int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
\r
4249 // It's important that we don't change any fields of this object
\r
4250 // prematurely. We set the following variables for the multiplier, grouping,
\r
4251 // etc., and then only change the actual object fields if everything parses
\r
4252 // correctly. This also lets us register the data from part 0 and ignore the
\r
4253 // part 1, except for the prefix and suffix.
\r
4254 StringBuilder prefix = new StringBuilder();
\r
4255 StringBuilder suffix = new StringBuilder();
\r
4256 int decimalPos = -1;
\r
4258 int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
\r
4259 byte groupingCount = -1;
\r
4260 byte groupingCount2 = -1;
\r
4263 int incrementPos = -1;
\r
4264 long incrementVal = 0;
\r
4265 byte expDigits = -1;
\r
4266 boolean expSignAlways = false;
\r
4268 // The affix is either the prefix or the suffix.
\r
4269 StringBuilder affix = prefix;
\r
4273 PARTLOOP: for (; pos < pattern.length(); ++pos) {
\r
4274 char ch = pattern.charAt(pos);
\r
4275 switch (subpart) {
\r
4276 case 0: // Pattern proper subpart (between prefix & suffix)
\r
4277 // Process the digits, decimal, and grouping characters. We record
\r
4278 // five pieces of information. We expect the digits to occur in the
\r
4279 // pattern ####00.00####, and we record the number of left digits,
\r
4280 // zero (central) digits, and right digits. The position of the last
\r
4281 // grouping character is recorded (should be somewhere within the
\r
4282 // first two blocks of characters), as is the position of the decimal
\r
4283 // point, if any (should be in the zero digits). If there is no
\r
4284 // decimal point, then there should be no right digits.
\r
4285 if (ch == digit) {
\r
4286 if (zeroDigitCount > 0 || sigDigitCount > 0) {
\r
4287 ++digitRightCount;
\r
4291 if (groupingCount >= 0 && decimalPos < 0) {
\r
4294 } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
\r
4295 if (digitRightCount > 0) {
\r
4296 patternError("Unexpected '" + ch + '\'', pattern);
\r
4298 if (ch == sigDigit) {
\r
4302 if (ch != zeroDigit) {
\r
4303 int p = digitLeftCount + zeroDigitCount + digitRightCount;
\r
4304 if (incrementPos >= 0) {
\r
4305 while (incrementPos < p) {
\r
4306 incrementVal *= 10;
\r
4312 incrementVal += ch - zeroDigit;
\r
4315 if (groupingCount >= 0 && decimalPos < 0) {
\r
4318 } else if (ch == groupingSeparator) {
\r
4319 // Bug 4212072 process the Localized pattern like
\r
4320 // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator
\r
4321 // == QUOTE) [Richard/GCL]
\r
4322 if (ch == QUOTE && (pos + 1) < pattern.length()) {
\r
4323 char after = pattern.charAt(pos + 1);
\r
4324 if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
\r
4325 // A quote outside quotes indicates either the opening
\r
4326 // quote or two quotes, which is a quote literal. That is,
\r
4327 // we have the first quote in 'do' or o''clock.
\r
4328 if (after == QUOTE) {
\r
4330 // Fall through to append(ch)
\r
4332 if (groupingCount < 0) {
\r
4333 subpart = 3; // quoted prefix subpart
\r
4335 // Transition to suffix subpart
\r
4336 subpart = 2; // suffix subpart
\r
4338 sub0Limit = pos--;
\r
4345 if (decimalPos >= 0) {
\r
4346 patternError("Grouping separator after decimal", pattern);
\r
4348 groupingCount2 = groupingCount;
\r
4349 groupingCount = 0;
\r
4350 } else if (ch == decimalSeparator) {
\r
4351 if (decimalPos >= 0) {
\r
4352 patternError("Multiple decimal separators", pattern);
\r
4354 // Intentionally incorporate the digitRightCount, even though it
\r
4355 // is illegal for this to be > 0 at this point. We check pattern
\r
4357 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
\r
4359 if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
\r
4360 if (expDigits >= 0) {
\r
4361 patternError("Multiple exponential symbols", pattern);
\r
4363 if (groupingCount >= 0) {
\r
4364 patternError("Grouping separator in exponential", pattern);
\r
4366 pos += exponent.length();
\r
4367 // Check for positive prefix
\r
4368 if (pos < pattern.length() && pattern.charAt(pos) == plus) {
\r
4369 expSignAlways = true;
\r
4372 // Use lookahead to parse out the exponential part of the
\r
4373 // pattern, then jump into suffix subpart.
\r
4375 while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {
\r
4380 // 1. Require at least one mantissa pattern digit
\r
4381 // 2. Disallow "#+ @" in mantissa
\r
4382 // 3. Require at least one exponent pattern digit
\r
4383 if (((digitLeftCount + zeroDigitCount) < 1 &&
\r
4384 (sigDigitCount + digitRightCount) < 1)
\r
4385 || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {
\r
4386 patternError("Malformed exponential", pattern);
\r
4389 // Transition to suffix subpart
\r
4390 subpart = 2; // suffix subpart
\r
4392 sub0Limit = pos--; // backup: for() will increment
\r
4396 case 1: // Prefix subpart
\r
4397 case 2: // Suffix subpart
\r
4398 // Process the prefix / suffix characters Process unquoted characters
\r
4399 // seen in prefix or suffix subpart.
\r
4401 // Several syntax characters implicitly begins the next subpart if we
\r
4402 // are in the prefix; otherwise they are illegal if unquoted.
\r
4403 if (ch == digit || ch == groupingSeparator || ch == decimalSeparator
\r
4404 || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {
\r
4405 // Any of these characters implicitly begins the
\r
4406 // next subpart if we are in the prefix
\r
4407 if (subpart == 1) { // prefix subpart
\r
4408 subpart = 0; // pattern proper subpart
\r
4409 sub0Start = pos--; // Reprocess this character
\r
4411 } else if (ch == QUOTE) {
\r
4412 // Bug 4212072 process the Localized pattern like
\r
4413 // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH",
\r
4414 // groupingSeparator == QUOTE) [Richard/GCL]
\r
4416 // A quote outside quotes indicates either the opening quote
\r
4417 // or two quotes, which is a quote literal. That is, we have
\r
4418 // the first quote in 'do' or o''clock.
\r
4419 if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
\r
4423 subpart += 2; // open quote
\r
4427 patternError("Unquoted special character '" + ch + '\'', pattern);
\r
4428 } else if (ch == CURRENCY_SIGN) {
\r
4429 // Use lookahead to determine if the currency sign is
\r
4430 // doubled or not.
\r
4431 boolean doubled = (pos + 1) < pattern.length() &&
\r
4432 pattern.charAt(pos + 1) == CURRENCY_SIGN;
\r
4434 // Bug 4212072 To meet the need of expandAffix(String,
\r
4435 // StirngBuffer) [Richard/GCL]
\r
4437 ++pos; // Skip over the doubled character
\r
4438 affix.append(ch); // append two: one here, one below
\r
4439 if ((pos + 1) < pattern.length() &&
\r
4440 pattern.charAt(pos + 1) == CURRENCY_SIGN) {
\r
4441 ++pos; // Skip over the tripled character
\r
4442 affix.append(ch); // append again
\r
4443 currencySignCount = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
\r
4445 currencySignCount = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
\r
4448 currencySignCount = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
\r
4450 // Fall through to append(ch)
\r
4451 } else if (ch == QUOTE) {
\r
4452 // A quote outside quotes indicates either the opening quote or
\r
4453 // two quotes, which is a quote literal. That is, we have the
\r
4454 // first quote in 'do' or o''clock.
\r
4455 if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
\r
4457 affix.append(ch); // append two: one here, one below
\r
4459 subpart += 2; // open quote
\r
4461 // Fall through to append(ch)
\r
4462 } else if (ch == separator) {
\r
4463 // Don't allow separators in the prefix, and don't allow
\r
4464 // separators in the second pattern (part == 1).
\r
4465 if (subpart == 1 || part == 1) {
\r
4466 patternError("Unquoted special character '" + ch + '\'', pattern);
\r
4468 sub2Limit = pos++;
\r
4469 break PARTLOOP; // Go to next part
\r
4470 } else if (ch == percent || ch == perMill) {
\r
4471 // Next handle characters which are appended directly.
\r
4472 if (multpl != 1) {
\r
4473 patternError("Too many percent/permille characters", pattern);
\r
4475 multpl = (ch == percent) ? 100 : 1000;
\r
4476 // Convert to non-localized pattern
\r
4477 ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
\r
4478 // Fall through to append(ch)
\r
4479 } else if (ch == minus) {
\r
4480 // Convert to non-localized pattern
\r
4481 ch = PATTERN_MINUS;
\r
4482 // Fall through to append(ch)
\r
4483 } else if (ch == padEscape) {
\r
4484 if (padPos >= 0) {
\r
4485 patternError("Multiple pad specifiers", pattern);
\r
4487 if ((pos + 1) == pattern.length()) {
\r
4488 patternError("Invalid pad specifier", pattern);
\r
4490 padPos = pos++; // Advance past pad char
\r
4491 padChar = pattern.charAt(pos);
\r
4496 case 3: // Prefix subpart, in quote
\r
4497 case 4: // Suffix subpart, in quote
\r
4498 // A quote within quotes indicates either the closing quote or two
\r
4499 // quotes, which is a quote literal. That is, we have the second quote
\r
4500 // in 'do' or 'don''t'.
\r
4501 if (ch == QUOTE) {
\r
4502 if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {
\r
4506 subpart -= 2; // close quote
\r
4508 // Fall through to append(ch)
\r
4510 // NOTE: In ICU 2.2 there was code here to parse quoted percent and
\r
4511 // permille characters _within quotes_ and give them special
\r
4512 // meaning. This is incorrect, since quoted characters are literals
\r
4513 // without special meaning.
\r
4519 if (subpart == 3 || subpart == 4) {
\r
4520 patternError("Unterminated quote", pattern);
\r
4523 if (sub0Limit == 0) {
\r
4524 sub0Limit = pattern.length();
\r
4527 if (sub2Limit == 0) {
\r
4528 sub2Limit = pattern.length();
\r
4531 // Handle patterns with no '0' pattern character. These patterns are legal,
\r
4532 // but must be recodified to make sense. "##.###" -> "#0.###". ".###" ->
\r
4535 // We allow patterns of the form "####" to produce a zeroDigitCount of zero
\r
4536 // (got that?); although this seems like it might make it possible for
\r
4537 // format() to produce empty strings, format() checks for this condition and
\r
4538 // outputs a zero digit in this situation. Having a zeroDigitCount of zero
\r
4539 // yields a minimum integer digits of zero, which allows proper round-trip
\r
4540 // patterns. We don't want "#" to become "#0" when toPattern() is called (even
\r
4541 // though that's what it really is, semantically).
\r
4542 if (zeroDigitCount == 0 && sigDigitCount == 0 &&
\r
4543 digitLeftCount > 0 && decimalPos >= 0) {
\r
4544 // Handle "###.###" and "###." and ".###"
\r
4545 int n = decimalPos;
\r
4547 ++n; // Handle ".###"
\r
4548 digitRightCount = digitLeftCount - n;
\r
4549 digitLeftCount = n - 1;
\r
4550 zeroDigitCount = 1;
\r
4553 // Do syntax checking on the digits, decimal points, and quotes.
\r
4554 if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)
\r
4555 || (decimalPos >= 0
\r
4556 && (sigDigitCount > 0
\r
4557 || decimalPos < digitLeftCount
\r
4558 || decimalPos > (digitLeftCount + zeroDigitCount)))
\r
4559 || groupingCount == 0
\r
4560 || groupingCount2 == 0
\r
4561 || (sigDigitCount > 0 && zeroDigitCount > 0)
\r
4562 || subpart > 2) { // subpart > 2 == unmatched quote
\r
4563 patternError("Malformed pattern", pattern);
\r
4566 // Make sure pad is at legal position before or after affix.
\r
4567 if (padPos >= 0) {
\r
4568 if (padPos == start) {
\r
4569 padPos = PAD_BEFORE_PREFIX;
\r
4570 } else if (padPos + 2 == sub0Start) {
\r
4571 padPos = PAD_AFTER_PREFIX;
\r
4572 } else if (padPos == sub0Limit) {
\r
4573 padPos = PAD_BEFORE_SUFFIX;
\r
4574 } else if (padPos + 2 == sub2Limit) {
\r
4575 padPos = PAD_AFTER_SUFFIX;
\r
4577 patternError("Illegal pad position", pattern);
\r
4582 // Set negative affixes temporarily to match the positive
\r
4583 // affixes. Fix this up later after processing both parts.
\r
4585 // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
\r
4587 posPrefixPattern = negPrefixPattern = prefix.toString();
\r
4588 posSuffixPattern = negSuffixPattern = suffix.toString();
\r
4590 useExponentialNotation = (expDigits >= 0);
\r
4591 if (useExponentialNotation) {
\r
4592 minExponentDigits = expDigits;
\r
4593 exponentSignAlwaysShown = expSignAlways;
\r
4595 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
\r
4596 // The effectiveDecimalPos is the position the decimal is at or would be
\r
4597 // at if there is no decimal. Note that if decimalPos<0, then
\r
4598 // digitTotalCount == digitLeftCount + zeroDigitCount.
\r
4599 int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
\r
4600 boolean useSigDig = (sigDigitCount > 0);
\r
4601 setSignificantDigitsUsed(useSigDig);
\r
4603 setMinimumSignificantDigits(sigDigitCount);
\r
4604 setMaximumSignificantDigits(sigDigitCount + digitRightCount);
\r
4606 int minInt = effectiveDecimalPos - digitLeftCount;
\r
4607 setMinimumIntegerDigits(minInt);
\r
4609 // Upper limit on integer and fraction digits for a Java double
\r
4611 setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt :
\r
4612 DOUBLE_INTEGER_DIGITS);
\r
4613 setMaximumFractionDigits(decimalPos >= 0 ?
\r
4614 (digitTotalCount - decimalPos) : 0);
\r
4615 setMinimumFractionDigits(decimalPos >= 0 ?
\r
4616 (digitLeftCount + zeroDigitCount - decimalPos) : 0);
\r
4618 setGroupingUsed(groupingCount > 0);
\r
4619 this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
\r
4620 this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
\r
4621 ? groupingCount2 : 0;
\r
4622 this.multiplier = multpl;
\r
4623 setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
\r
4624 if (padPos >= 0) {
\r
4625 padPosition = padPos;
\r
4626 formatWidth = sub0Limit - sub0Start; // to be fixed up below
\r
4631 if (incrementVal != 0) {
\r
4632 // BigDecimal scale cannot be negative (even though this makes perfect
\r
4633 // sense), so we need to handle this.
\r
4634 int scale = incrementPos - effectiveDecimalPos;
\r
4635 roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
\r
4637 roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);
\r
4639 setRoundingDouble();
\r
4640 roundingMode = BigDecimal.ROUND_HALF_EVEN;
\r
4642 setRoundingIncrement((BigDecimal) null);
\r
4645 // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)
\r
4647 negPrefixPattern = prefix.toString();
\r
4648 negSuffixPattern = suffix.toString();
\r
4649 gotNegative = true;
\r
4654 // Bug 4140009 Process the empty pattern [Richard/GCL]
\r
4655 if (pattern.length() == 0) {
\r
4656 posPrefixPattern = posSuffixPattern = "";
\r
4657 setMinimumIntegerDigits(0);
\r
4658 setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
\r
4659 setMinimumFractionDigits(0);
\r
4660 setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
\r
4663 // If there was no negative pattern, or if the negative pattern is identical to
\r
4664 // the positive pattern, then prepend the minus sign to the positive pattern to
\r
4665 // form the negative pattern.
\r
4667 // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
\r
4669 if (!gotNegative ||
\r
4670 (negPrefixPattern.equals(posPrefixPattern)
\r
4671 && negSuffixPattern.equals(posSuffixPattern))) {
\r
4672 negSuffixPattern = posSuffixPattern;
\r
4673 negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
\r
4675 setLocale(null, null);
\r
4676 // save the pattern
\r
4677 formatPattern = pattern;
\r
4678 // initialize currencyPluralInfo if needed
\r
4679 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT
\r
4680 && currencyPluralInfo == null) {
\r
4681 currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
\r
4686 * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.
\r
4688 private void setRoundingDouble() {
\r
4689 if (roundingIncrementICU == null) {
\r
4690 roundingDouble = 0.0d;
\r
4691 roundingDoubleReciprocal = 0.0d;
\r
4693 roundingDouble = roundingIncrementICU.doubleValue();
\r
4694 setRoundingDoubleReciprocal(
\r
4695 BigDecimal.ONE.divide(roundingIncrementICU, BigDecimal.ROUND_HALF_EVEN)
\r
4700 private void patternError(String msg, String pattern) {
\r
4701 throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
\r
4705 // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits
\r
4706 // for a Java double [Richard/GCL]
\r
4709 * Sets the maximum number of digits allowed in the integer portion of a number. This
\r
4710 * override limits the integer digit count to 309.
\r
4712 * @see NumberFormat#setMaximumIntegerDigits
\r
4715 public void setMaximumIntegerDigits(int newValue) {
\r
4716 super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
\r
4720 * Sets the minimum number of digits allowed in the integer portion of a number. This
\r
4721 * override limits the integer digit count to 309.
\r
4723 * @see NumberFormat#setMinimumIntegerDigits
\r
4726 public void setMinimumIntegerDigits(int newValue) {
\r
4727 super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
\r
4731 * {@icu} Returns the minimum number of significant digits that will be
\r
4732 * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
\r
4735 * @return the fewest significant digits that will be shown
\r
4738 public int getMinimumSignificantDigits() {
\r
4739 return minSignificantDigits;
\r
4743 * {@icu} Returns the maximum number of significant digits that will be
\r
4744 * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}
\r
4747 * @return the most significant digits that will be shown
\r
4750 public int getMaximumSignificantDigits() {
\r
4751 return maxSignificantDigits;
\r
4755 * {@icu} Sets the minimum number of significant digits that will be displayed. If
\r
4756 * <code>min</code> is less than one then it is set to one. If the maximum significant
\r
4757 * digits count is less than <code>min</code>, then it is set to
\r
4758 * <code>min</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
\r
4761 * @param min the fewest significant digits to be shown
\r
4764 public void setMinimumSignificantDigits(int min) {
\r
4768 // pin max sig dig to >= min
\r
4769 int max = Math.max(maxSignificantDigits, min);
\r
4770 minSignificantDigits = min;
\r
4771 maxSignificantDigits = max;
\r
4775 * {@icu} Sets the maximum number of significant digits that will be displayed. If
\r
4776 * <code>max</code> is less than one then it is set to one. If the minimum significant
\r
4777 * digits count is greater than <code>max</code>, then it is set to
\r
4778 * <code>max</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}
\r
4781 * @param max the most significant digits to be shown
\r
4784 public void setMaximumSignificantDigits(int max) {
\r
4788 // pin min sig dig to 1..max
\r
4789 int min = Math.min(minSignificantDigits, max);
\r
4790 minSignificantDigits = min;
\r
4791 maxSignificantDigits = max;
\r
4795 * {@icu} Returns true if significant digits are in use or false if integer and
\r
4796 * fraction digit counts are in use.
\r
4798 * @return true if significant digits are in use
\r
4801 public boolean areSignificantDigitsUsed() {
\r
4802 return useSignificantDigits;
\r
4806 * {@icu} Sets whether significant digits are in use, or integer and fraction digit
\r
4807 * counts are in use.
\r
4809 * @param useSignificantDigits true to use significant digits, or false to use integer
\r
4810 * and fraction digit counts
\r
4813 public void setSignificantDigitsUsed(boolean useSignificantDigits) {
\r
4814 this.useSignificantDigits = useSignificantDigits;
\r
4818 * Sets the <tt>Currency</tt> object used to display currency amounts. This takes
\r
4819 * effect immediately, if this format is a currency format. If this format is not a
\r
4820 * currency format, then the currency object is used if and when this object becomes a
\r
4821 * currency format through the application of a new pattern.
\r
4823 * @param theCurrency new currency object to use. Must not be null.
\r
4826 public void setCurrency(Currency theCurrency) {
\r
4827 // If we are a currency format, then modify our affixes to
\r
4828 // encode the currency symbol for the given currency in our
\r
4829 // locale, and adjust the decimal digits and rounding for the
\r
4830 // given currency.
\r
4832 super.setCurrency(theCurrency);
\r
4833 if (theCurrency != null) {
\r
4834 boolean[] isChoiceFormat = new boolean[1];
\r
4835 String s = theCurrency.getName(symbols.getULocale(),
\r
4836 Currency.SYMBOL_NAME, isChoiceFormat);
\r
4837 symbols.setCurrencySymbol(s);
\r
4838 symbols.setInternationalCurrencySymbol(theCurrency.getCurrencyCode());
\r
4841 if (currencySignCount > 0) {
\r
4842 if (theCurrency != null) {
\r
4843 setRoundingIncrement(theCurrency.getRoundingIncrement());
\r
4844 int d = theCurrency.getDefaultFractionDigits();
\r
4845 setMinimumFractionDigits(d);
\r
4846 setMaximumFractionDigits(d);
\r
4848 expandAffixes(null);
\r
4853 * Returns the currency in effect for this formatter. Subclasses should override this
\r
4854 * method as needed. Unlike getCurrency(), this method should never return null.
\r
4857 * @deprecated This API is ICU internal only.
\r
4859 protected Currency getEffectiveCurrency() {
\r
4860 Currency c = getCurrency();
\r
4862 c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
\r
4868 * Sets the maximum number of digits allowed in the fraction portion of a number. This
\r
4869 * override limits the fraction digit count to 340.
\r
4871 * @see NumberFormat#setMaximumFractionDigits
\r
4874 public void setMaximumFractionDigits(int newValue) {
\r
4875 super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
\r
4879 * Sets the minimum number of digits allowed in the fraction portion of a number. This
\r
4880 * override limits the fraction digit count to 340.
\r
4882 * @see NumberFormat#setMinimumFractionDigits
\r
4885 public void setMinimumFractionDigits(int newValue) {
\r
4886 super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
\r
4890 * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The
\r
4891 * default value is false.
\r
4893 * @param value true if {@link #parse(String, ParsePosition)}
\r
4894 * returns BigDecimal.
\r
4897 public void setParseBigDecimal(boolean value) {
\r
4898 parseBigDecimal = value;
\r
4902 * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.
\r
4904 * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.
\r
4907 public boolean isParseBigDecimal() {
\r
4908 return parseBigDecimal;
\r
4911 private void writeObject(ObjectOutputStream stream) throws IOException {
\r
4912 // Ticket#6449 Format.Field instances are not serializable. When
\r
4913 // formatToCharacterIterator is called, attributes (ArrayList) stores
\r
4914 // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is
\r
4915 // not serializable, we need to clear the contents of the list when writeObject is
\r
4916 // called. We could remove the field or make it transient, but it will break
\r
4917 // serialization compatibility.
\r
4918 attributes.clear();
\r
4920 stream.defaultWriteObject();
\r
4924 * First, read the default serializable fields from the stream. Then if
\r
4925 * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was
\r
4926 * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since
\r
4927 * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the
\r
4928 * maximum allowed value so that default serialization will work properly if this
\r
4929 * object is streamed out again.
\r
4931 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
\r
4932 stream.defaultReadObject();
\r
4934 // Bug 4185761 validate fields [Richard/GCL]
\r
4936 // We only need to check the maximum counts because NumberFormat .readObject has
\r
4937 // already ensured that the maximum is greater than the minimum count.
\r
4939 // Commented for compatibility with previous version, and reserved for further use
\r
4940 // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
\r
4941 // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new
\r
4942 // InvalidObjectException("Digit count out of range"); }
\r
4945 // Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and
\r
4946 // maximumFractionDigits to DOUBLE_FRACTION_DIGITS
\r
4948 if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
\r
4949 setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
\r
4951 if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
\r
4952 setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
\r
4954 if (serialVersionOnStream < 2) {
\r
4955 exponentSignAlwaysShown = false;
\r
4956 setInternalRoundingIncrement(null);
\r
4957 setRoundingDouble();
\r
4958 roundingMode = BigDecimal.ROUND_HALF_EVEN;
\r
4961 padPosition = PAD_BEFORE_PREFIX;
\r
4962 if (serialVersionOnStream < 1) {
\r
4963 // Didn't have exponential fields
\r
4964 useExponentialNotation = false;
\r
4967 if (serialVersionOnStream < 3) {
\r
4968 // Versions prior to 3 do not store a currency object. Create one to match
\r
4969 // the DecimalFormatSymbols object.
\r
4970 setCurrencyForSymbols();
\r
4972 serialVersionOnStream = currentSerialVersion;
\r
4973 digitList = new DigitList();
\r
4975 if (roundingIncrement != null) {
\r
4976 setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
\r
4977 setRoundingDouble();
\r
4981 private void setInternalRoundingIncrement(BigDecimal value) {
\r
4982 roundingIncrementICU = value;
\r
4983 roundingIncrement = value == null ? null : value.toBigDecimal();
\r
4986 // ----------------------------------------------------------------------
\r
4987 // INSTANCE VARIABLES
\r
4988 // ----------------------------------------------------------------------
\r
4990 private transient DigitList digitList = new DigitList();
\r
4993 * The symbol used as a prefix when formatting positive numbers, e.g. "+".
\r
4996 * @see #getPositivePrefix
\r
4998 private String positivePrefix = "";
\r
5001 * The symbol used as a suffix when formatting positive numbers. This is often an
\r
5005 * @see #getPositiveSuffix
\r
5007 private String positiveSuffix = "";
\r
5010 * The symbol used as a prefix when formatting negative numbers, e.g. "-".
\r
5013 * @see #getNegativePrefix
\r
5015 private String negativePrefix = "-";
\r
5018 * The symbol used as a suffix when formatting negative numbers. This is often an
\r
5022 * @see #getNegativeSuffix
\r
5024 private String negativeSuffix = "";
\r
5027 * The prefix pattern for non-negative numbers. This variable corresponds to
\r
5028 * <code>positivePrefix</code>.
\r
5030 * <p>This pattern is expanded by the method <code>expandAffix()</code> to
\r
5031 * <code>positivePrefix</code> to update the latter to reflect changes in
\r
5032 * <code>symbols</code>. If this variable is <code>null</code> then
\r
5033 * <code>positivePrefix</code> is taken as a literal value that does not change when
\r
5034 * <code>symbols</code> changes. This variable is always <code>null</code> for
\r
5035 * <code>DecimalFormat</code> objects older than stream version 2 restored from
\r
5041 private String posPrefixPattern;
\r
5044 * The suffix pattern for non-negative numbers. This variable corresponds to
\r
5045 * <code>positiveSuffix</code>. This variable is analogous to
\r
5046 * <code>posPrefixPattern</code>; see that variable for further documentation.
\r
5051 private String posSuffixPattern;
\r
5054 * The prefix pattern for negative numbers. This variable corresponds to
\r
5055 * <code>negativePrefix</code>. This variable is analogous to
\r
5056 * <code>posPrefixPattern</code>; see that variable for further documentation.
\r
5061 private String negPrefixPattern;
\r
5064 * The suffix pattern for negative numbers. This variable corresponds to
\r
5065 * <code>negativeSuffix</code>. This variable is analogous to
\r
5066 * <code>posPrefixPattern</code>; see that variable for further documentation.
\r
5071 private String negSuffixPattern;
\r
5074 * Formatter for ChoiceFormat-based currency names. If this field is not null, then
\r
5075 * delegate to it to format currency symbols.
\r
5079 private ChoiceFormat currencyChoice;
\r
5082 * The multiplier for use in percent, permill, etc.
\r
5085 * @see #getMultiplier
\r
5087 private int multiplier = 1;
\r
5090 * The number of digits between grouping separators in the integer portion of a
\r
5091 * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true.
\r
5094 * @see #getGroupingSize
\r
5095 * @see NumberFormat#isGroupingUsed
\r
5097 private byte groupingSize = 3; // invariant, > 0 if useThousands
\r
5100 * The secondary grouping size. This is only used for Hindi numerals, which use a
\r
5101 * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this
\r
5102 * value is less than 1, then secondary grouping is equal to the primary grouping.
\r
5105 private byte groupingSize2 = 0;
\r
5108 * If true, forces the decimal separator to always appear in a formatted number, even
\r
5109 * if the fractional part of the number is zero.
\r
5112 * @see #isDecimalSeparatorAlwaysShown
\r
5114 private boolean decimalSeparatorAlwaysShown = false;
\r
5117 * The <code>DecimalFormatSymbols</code> object used by this format. It contains the
\r
5118 * symbols used to format numbers, e.g. the grouping separator, decimal separator, and
\r
5122 * @see #setDecimalFormatSymbols
\r
5123 * @see DecimalFormatSymbols
\r
5125 private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
\r
5128 * True to use significant digits rather than integer and fraction digit counts.
\r
5133 private boolean useSignificantDigits = false;
\r
5136 * The minimum number of significant digits to show. Must be >= 1 and <=
\r
5137 * maxSignificantDigits. Ignored unless useSignificantDigits == true.
\r
5142 private int minSignificantDigits = 1;
\r
5145 * The maximum number of significant digits to show. Must be >=
\r
5146 * minSignficantDigits. Ignored unless useSignificantDigits == true.
\r
5151 private int maxSignificantDigits = 6;
\r
5154 * True to force the use of exponential (i.e. scientific) notation
\r
5155 * when formatting numbers.
\r
5157 *<p> Note that the JDK 1.2 public API provides no way to set this
\r
5158 * field, even though it is supported by the implementation and
\r
5159 * the stream format. The intent is that this will be added to the
\r
5160 * API in the future.
\r
5164 private boolean useExponentialNotation; // Newly persistent in JDK 1.2
\r
5167 * The minimum number of digits used to display the exponent when a number is
\r
5168 * formatted in exponential notation. This field is ignored if
\r
5169 * <code>useExponentialNotation</code> is not true.
\r
5171 * <p>Note that the JDK 1.2 public API provides no way to set this field, even though
\r
5172 * it is supported by the implementation and the stream format. The intent is that
\r
5173 * this will be added to the API in the future.
\r
5177 private byte minExponentDigits; // Newly persistent in JDK 1.2
\r
5180 * If true, the exponent is always prefixed with either the plus sign or the minus
\r
5181 * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has
\r
5182 * no effect unless <code>useExponentialNotation</code> is true.
\r
5185 * @since AlphaWorks NumberFormat
\r
5187 private boolean exponentSignAlwaysShown = false;
\r
5190 * The value to which numbers are rounded during formatting. For example, if the
\r
5191 * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
\r
5192 * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
\r
5193 * positive value if rounding is in effect. Default value <code>null</code>.
\r
5196 * @since AlphaWorks NumberFormat
\r
5198 // Note: this is kept in sync with roundingIncrementICU.
\r
5199 // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
\r
5200 private java.math.BigDecimal roundingIncrement = null;
\r
5203 * The value to which numbers are rounded during formatting. For example, if the
\r
5204 * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3
\r
5205 * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a
\r
5206 * positive value if rounding is in effect. Default value <code>null</code>. WARNING:
\r
5207 * the roundingIncrement value is the one serialized.
\r
5210 * @since AlphaWorks NumberFormat
\r
5212 private transient BigDecimal roundingIncrementICU = null;
\r
5215 * The rounding increment as a double. If this value is <= 0, then no rounding is
\r
5216 * done. This value is <code>roundingIncrementICU.doubleValue()</code>. Default value
\r
5219 private transient double roundingDouble = 0.0;
\r
5222 * If the roundingDouble is the reciprocal of an integer (the most common case!), this
\r
5223 * is set to be that integer. Otherwise it is 0.0.
\r
5225 private transient double roundingDoubleReciprocal = 0.0;
\r
5228 * The rounding mode. This value controls any rounding operations which occur when
\r
5229 * applying a rounding increment or when reducing the number of fraction digits to
\r
5230 * satisfy a maximum fraction digits limit. The value may assume any of the
\r
5231 * <code>BigDecimal</code> rounding mode values. Default value
\r
5232 * <code>BigDecimal.ROUND_HALF_EVEN</code>.
\r
5235 * @since AlphaWorks NumberFormat
\r
5237 private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
\r
5240 * Operations on <code>BigDecimal</code> numbers are controlled by a {@link
\r
5241 * MathContext} object, which provides the context (precision and other information)
\r
5242 * for the operation. The default <code>MathContext</code> settings are
\r
5243 * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>;
\r
5244 * these settings perform fixed point arithmetic with unlimited precision, as defined
\r
5245 * for the original BigDecimal class in Java 1.1 and Java 1.2
\r
5247 // context for plain unlimited math
\r
5248 private MathContext mathContext = new MathContext(0, MathContext.PLAIN);
\r
5251 * The padded format width, or zero if there is no padding. Must be >= 0. Default
\r
5255 * @since AlphaWorks NumberFormat
\r
5257 private int formatWidth = 0;
\r
5260 * The character used to pad the result of format to <code>formatWidth</code>, if
\r
5261 * padding is in effect. Default value ' '.
\r
5264 * @since AlphaWorks NumberFormat
\r
5266 private char pad = ' ';
\r
5269 * The position in the string at which the <code>pad</code> character will be
\r
5270 * inserted, if padding is in effect. Must have a value from
\r
5271 * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value
\r
5272 * <code>PAD_BEFORE_PREFIX</code>.
\r
5275 * @since AlphaWorks NumberFormat
\r
5277 private int padPosition = PAD_BEFORE_PREFIX;
\r
5280 * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than
\r
5281 * Long, Double or BigDecimal except special values. This property is introduced for
\r
5282 * J2SE 5 compatibility support.
\r
5286 * @see #setParseBigDecimal(boolean)
\r
5287 * @see #isParseBigDecimal()
\r
5289 private boolean parseBigDecimal = false;
\r
5291 // ----------------------------------------------------------------------
\r
5293 static final int currentSerialVersion = 3;
\r
5296 * The internal serial version which says which version was written Possible values
\r
5301 * <li><b>0</b> (default): versions before JDK 1.2
\r
5303 * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
\r
5304 * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
\r
5306 * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad,
\r
5307 * padPosition, exponentSignAlwaysShown, roundingIncrement.
\r
5309 * <li><b>3</b>: ICU 2.2. Adds currency object.
\r
5315 private int serialVersionOnStream = currentSerialVersion;
\r
5317 // ----------------------------------------------------------------------
\r
5319 // ----------------------------------------------------------------------
\r
5322 * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
\r
5323 * specify pad characters inserted before the prefix.
\r
5325 * @see #setPadPosition
\r
5326 * @see #getPadPosition
\r
5327 * @see #PAD_AFTER_PREFIX
\r
5328 * @see #PAD_BEFORE_SUFFIX
\r
5329 * @see #PAD_AFTER_SUFFIX
\r
5332 public static final int PAD_BEFORE_PREFIX = 0;
\r
5335 * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
\r
5336 * specify pad characters inserted after the prefix.
\r
5338 * @see #setPadPosition
\r
5339 * @see #getPadPosition
\r
5340 * @see #PAD_BEFORE_PREFIX
\r
5341 * @see #PAD_BEFORE_SUFFIX
\r
5342 * @see #PAD_AFTER_SUFFIX
\r
5345 public static final int PAD_AFTER_PREFIX = 1;
\r
5348 * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
\r
5349 * specify pad characters inserted before the suffix.
\r
5351 * @see #setPadPosition
\r
5352 * @see #getPadPosition
\r
5353 * @see #PAD_BEFORE_PREFIX
\r
5354 * @see #PAD_AFTER_PREFIX
\r
5355 * @see #PAD_AFTER_SUFFIX
\r
5358 public static final int PAD_BEFORE_SUFFIX = 2;
\r
5361 * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to
\r
5362 * specify pad characters inserted after the suffix.
\r
5364 * @see #setPadPosition
\r
5365 * @see #getPadPosition
\r
5366 * @see #PAD_BEFORE_PREFIX
\r
5367 * @see #PAD_AFTER_PREFIX
\r
5368 * @see #PAD_BEFORE_SUFFIX
\r
5371 public static final int PAD_AFTER_SUFFIX = 3;
\r
5373 // Constants for characters used in programmatic (unlocalized) patterns.
\r
5374 private static final char PATTERN_ZERO_DIGIT = '0';
\r
5375 private static final char PATTERN_GROUPING_SEPARATOR = ',';
\r
5376 private static final char PATTERN_DECIMAL_SEPARATOR = '.';
\r
5377 private static final char PATTERN_DIGIT = '#';
\r
5378 static final char PATTERN_SIGNIFICANT_DIGIT = '@';
\r
5379 static final char PATTERN_EXPONENT = 'E';
\r
5380 static final char PATTERN_PLUS_SIGN = '+';
\r
5383 private static final char PATTERN_PER_MILLE = '\u2030';
\r
5384 private static final char PATTERN_PERCENT = '%';
\r
5385 static final char PATTERN_PAD_ESCAPE = '*';
\r
5387 * Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
\r
5389 private static final char PATTERN_MINUS = '-';
\r
5392 private static final char PATTERN_SEPARATOR = ';';
\r
5394 // Pad escape is package private to allow access by DecimalFormatSymbols.
\r
5395 // Also plus sign. Also exponent.
\r
5398 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in
\r
5399 * patterns and substitued with either the currency symbol, or if it is doubled, with
\r
5400 * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then
\r
5401 * the decimal separator is replaced with the monetary decimal separator.
\r
5403 * The CURRENCY_SIGN is not localized.
\r
5405 private static final char CURRENCY_SIGN = '\u00A4';
\r
5407 private static final char QUOTE = '\'';
\r
5410 * Upper limit on integer and fraction digits for a Java double [Richard/GCL]
\r
5412 static final int DOUBLE_INTEGER_DIGITS = 309;
\r
5413 static final int DOUBLE_FRACTION_DIGITS = 340;
\r
5416 * When someone turns on scientific mode, we assume that more than this number of
\r
5417 * digits is due to flipping from some other mode that didn't restrict the maximum,
\r
5418 * and so we force 1 integer digit. We don't bother to track and see if someone is
\r
5419 * using exponential notation with more than this number, it wouldn't make sense
\r
5420 * anyway, and this is just to make sure that someone turning on scientific mode with
\r
5421 * default settings doesn't end up with lots of zeroes.
\r
5423 static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
\r
5425 // Proclaim JDK 1.1 serial compatibility.
\r
5426 private static final long serialVersionUID = 864413376551465018L;
\r
5428 private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>();
\r
5430 // The following are used in currency format
\r
5432 // -- triple currency sign char array
\r
5433 // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
\r
5434 // -- triple currency sign string
\r
5435 // private static final String tripleCurrencyStr = new String(tripleCurrencySign);
\r
5437 // -- default currency plural pattern char array
\r
5438 // private static final char[] defaultCurrencyPluralPatternChar =
\r
5439 // {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
\r
5440 // -- default currency plural pattern string
\r
5441 // private static final String defaultCurrencyPluralPattern =
\r
5442 // new String(defaultCurrencyPluralPatternChar);
\r
5444 // pattern used in this formatter
\r
5445 private String formatPattern = "";
\r
5446 // style is only valid when decimal formatter is constructed by
\r
5447 // DecimalFormat(pattern, decimalFormatSymbol, style)
\r
5448 private int style = NumberFormat.NUMBERSTYLE;
\r
5450 * Represents whether this is a currency format, and which currency format style. 0:
\r
5451 * not currency format type; 1: currency style -- symbol name, such as "$" for US
\r
5452 * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style
\r
5453 * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for
\r
5454 * "3.00 US Dollars".
\r
5456 private int currencySignCount = 0;
\r
5459 * For parsing purposes, we need to remember all prefix patterns and suffix patterns
\r
5460 * of every currency format pattern, including the pattern of the default currency
\r
5461 * style, ISO currency style, and plural currency style. The patterns are set through
\r
5462 * applyPattern. The following are used to represent the affix patterns in currency
\r
5465 private static final class AffixForCurrency {
\r
5466 // negative prefix pattern
\r
5467 private String negPrefixPatternForCurrency = null;
\r
5468 // negative suffix pattern
\r
5469 private String negSuffixPatternForCurrency = null;
\r
5470 // positive prefix pattern
\r
5471 private String posPrefixPatternForCurrency = null;
\r
5472 // positive suffix pattern
\r
5473 private String posSuffixPatternForCurrency = null;
\r
5474 private int patternType;
\r
5476 public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix,
\r
5477 String posSuffix, int type) {
\r
5478 negPrefixPatternForCurrency = negPrefix;
\r
5479 negSuffixPatternForCurrency = negSuffix;
\r
5480 posPrefixPatternForCurrency = posPrefix;
\r
5481 posSuffixPatternForCurrency = posSuffix;
\r
5482 patternType = type;
\r
5485 public String getNegPrefix() {
\r
5486 return negPrefixPatternForCurrency;
\r
5489 public String getNegSuffix() {
\r
5490 return negSuffixPatternForCurrency;
\r
5493 public String getPosPrefix() {
\r
5494 return posPrefixPatternForCurrency;
\r
5497 public String getPosSuffix() {
\r
5498 return posSuffixPatternForCurrency;
\r
5501 public int getPatternType() {
\r
5502 return patternType;
\r
5506 // Affix pattern set for currency. It is a set of AffixForCurrency, each element of
\r
5507 // the set saves the negative prefix, negative suffix, positive prefix, and positive
\r
5508 // suffix of a pattern.
\r
5509 private transient Set<AffixForCurrency> affixPatternsForCurrency = null;
\r
5511 // For currency parsing. Since currency parsing needs to parse against all currency
\r
5512 // patterns, before the parsing, we need to set up the affix patterns for all currencies.
\r
5513 private transient boolean isReadyForParsing = false;
\r
5515 // Information needed for DecimalFormat to format/parse currency plural.
\r
5516 private CurrencyPluralInfo currencyPluralInfo = null;
\r