3 *******************************************************************************
\r
4 * Copyright (C) 1996-2009, International Business Machines Corporation and *
\r
5 * others. All Rights Reserved. *
\r
6 *******************************************************************************
\r
8 package com.ibm.icu.text;
\r
10 import java.io.IOException;
\r
11 import java.io.ObjectInputStream;
\r
12 import java.math.BigInteger;
\r
13 import java.text.ChoiceFormat;
\r
14 import java.text.FieldPosition;
\r
15 import java.text.ParsePosition;
\r
16 import java.util.HashSet;
\r
17 import java.util.Iterator;
\r
18 import java.util.Set;
\r
20 //#if defined(FOUNDATION10)
\r
22 import java.io.ObjectOutputStream;
\r
25 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
27 import java.text.AttributedCharacterIterator;
\r
28 import java.text.AttributedString;
\r
29 import java.text.Format;
\r
30 import java.util.ArrayList;
\r
33 import com.ibm.icu.impl.UCharacterProperty;
\r
34 import com.ibm.icu.impl.Utility;
\r
35 import com.ibm.icu.lang.UCharacter;
\r
36 import com.ibm.icu.math.BigDecimal;
\r
37 import com.ibm.icu.util.Currency;
\r
38 import com.ibm.icu.util.CurrencyAmount;
\r
39 import com.ibm.icu.util.ULocale;
\r
40 import com.ibm.icu.math.MathContext;
\r
42 //This is an enhanced version of DecimalFormat that is based on the standard version in the JDK.
\r
44 * <code>DecimalFormat</code> is a concrete subclass of
\r
45 * {@link NumberFormat} that formats decimal numbers. It has a variety of
\r
46 * features designed to make it possible to parse and format numbers in any
\r
47 * locale, including support for Western, Arabic, or Indic digits. It also
\r
48 * supports different flavors of numbers, including integers ("123"),
\r
49 * fixed-point numbers ("123.4"), scientific notation ("1.23E4"), percentages
\r
50 * ("12%"), and currency amounts ("$123.00", "USD123.00", "123.00 US dollars").
\r
51 * All of these flavors can be easily localized.
\r
54 * <p>To obtain a {@link NumberFormat} for a specific locale (including the
\r
55 * default locale) call one of <code>NumberFormat</code>'s factory methods such
\r
56 * as {@link NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code>
\r
57 * constructors directly, unless you know what you are doing, since the
\r
58 * {@link NumberFormat} factory methods may return subclasses other than
\r
59 * <code>DecimalFormat</code>. If you need to customize the format object, do
\r
60 * something like this:
\r
63 * NumberFormat f = NumberFormat.getInstance(loc);
\r
64 * if (f instanceof DecimalFormat) {
\r
65 * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
\r
66 * }</pre></blockquote>
\r
68 * <p><strong>Example Usage</strong>
\r
71 * <strong>// Print out a number using the localized number, currency,
\r
72 * // and percent format for each locale</strong>
\r
73 * Locale[] locales = NumberFormat.getAvailableLocales();
\r
74 * double myNumber = -1234.56;
\r
75 * NumberFormat format;
\r
76 * for (int j=0; j<3; ++j) {
\r
77 * System.out.println("FORMAT");
\r
78 * for (int i = 0; i < locales.length; ++i) {
\r
79 * if (locales[i].getCountry().length() == 0) {
\r
80 * // Skip language-only locales
\r
83 * System.out.print(locales[i].getDisplayName());
\r
86 * format = NumberFormat.getInstance(locales[i]); break;
\r
88 * format = NumberFormat.getCurrencyInstance(locales[i]); break;
\r
90 * format = NumberFormat.getPercentInstance(locales[i]); break;
\r
93 * // Assume format is a DecimalFormat
\r
94 * System.out.print(": " + ((DecimalFormat) format).toPattern()
\r
95 * + " -> " + form.format(myNumber));
\r
96 * } catch (Exception e) {}
\r
98 * System.out.println(" -> " + format.parse(form.format(myNumber)));
\r
99 * } catch (ParseException e) {}
\r
101 * }</pre></blockquote>
\r
104 * Another example use getInstance(style)
\r
107 * <strong>// Print out a number using the localized number, currency,
\r
108 * // percent, scientific, integer, iso currency, and plural currency
\r
109 * // format for each locale</strong>
\r
110 * ULocale locale = new ULocale("en_US");
\r
111 * double myNumber = 1234.56;
\r
112 * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {
\r
113 * NumberFormat format = NumberFormat.getInstance(locale, j);
\r
115 * // Assume format is a DecimalFormat
\r
116 * System.out.print(": " + ((DecimalFormat) format).toPattern()
\r
117 * + " -> " + form.format(myNumber));
\r
118 * } catch (Exception e) {}
\r
120 * System.out.println(" -> " + format.parse(form.format(myNumber)));
\r
121 * } catch (ParseException e) {}
\r
122 * }</pre></blockquote>
\r
124 * <h4>Patterns</h4>
\r
126 * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of
\r
127 * <em>symbols</em>. The pattern may be set directly using
\r
128 * {@link #applyPattern}, or indirectly using other API methods which
\r
129 * manipulate aspects of the pattern, such as the minimum number of integer
\r
130 * digits. The symbols are stored in a {@link DecimalFormatSymbols}
\r
131 * object. When using the {@link NumberFormat} factory methods, the
\r
132 * pattern and symbols are read from ICU's locale data.
\r
134 * <h4>Special Pattern Characters</h4>
\r
136 * <p>Many characters in a pattern are taken literally; they are matched during
\r
137 * parsing and output unchanged during formatting. Special characters, on the
\r
138 * other hand, stand for other characters, strings, or classes of characters.
\r
139 * For example, the '#' character is replaced by a localized digit. Often the
\r
140 * replacement character is the same as the pattern character; in the U.S. locale,
\r
141 * the ',' grouping character is replaced by ','. However, the replacement is
\r
142 * still happening, and if the symbols are modified, the grouping character
\r
143 * changes. Some special characters affect the behavior of the formatter by
\r
144 * their presence; for example, if the percent character is seen, then the
\r
145 * value is multiplied by 100 before being displayed.
\r
147 * <p>To insert a special character in a pattern as a literal, that is, without
\r
148 * any special meaning, the character must be quoted. There are some exceptions to
\r
149 * this which are noted below.
\r
151 * <p>The characters listed here are used in non-localized patterns. Localized
\r
152 * patterns use the corresponding characters taken from this formatter's
\r
153 * {@link DecimalFormatSymbols} object instead, and these characters lose
\r
154 * their special status. Two exceptions are the currency sign and quote, which
\r
155 * are not localized.
\r
158 * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
\r
159 * location, localized, and meaning.">
\r
160 * <tr bgcolor="#ccccff">
\r
161 * <th align=left>Symbol
\r
162 * <th align=left>Location
\r
163 * <th align=left>Localized?
\r
164 * <th align=left>Meaning
\r
166 * <td><code>0</code>
\r
170 * <tr valign=top bgcolor="#eeeeff">
\r
171 * <td><code>1-9</code>
\r
174 * <td>'1' through '9' indicate rounding.
\r
177 * <td><code>@</code>
\r
180 * <td>Significant digit
\r
181 * <tr valign=top bgcolor="#eeeeff">
\r
182 * <td><code>#</code>
\r
185 * <td>Digit, zero shows as absent
\r
187 * <td><code>.</code>
\r
190 * <td>Decimal separator or monetary decimal separator
\r
191 * <tr valign=top bgcolor="#eeeeff">
\r
192 * <td><code>-</code>
\r
197 * <td><code>,</code>
\r
200 * <td>Grouping separator
\r
201 * <tr valign=top bgcolor="#eeeeff">
\r
202 * <td><code>E</code>
\r
205 * <td>Separates mantissa and exponent in scientific notation.
\r
206 * <em>Need not be quoted in prefix or suffix.</em>
\r
208 * <td><code>+</code>
\r
211 * <td>Prefix positive exponents with localized plus sign.
\r
212 * <em>Need not be quoted in prefix or suffix.</em>
\r
213 * <tr valign=top bgcolor="#eeeeff">
\r
214 * <td><code>;</code>
\r
215 * <td>Subpattern boundary
\r
217 * <td>Separates positive and negative subpatterns
\r
219 * <td><code>%</code>
\r
220 * <td>Prefix or suffix
\r
222 * <td>Multiply by 100 and show as percentage
\r
223 * <tr valign=top bgcolor="#eeeeff">
\r
224 * <td><code>\u2030</code>
\r
225 * <td>Prefix or suffix
\r
227 * <td>Multiply by 1000 and show as per mille
\r
229 * <td><code>¤</code> (<code>\u00A4</code>)
\r
230 * <td>Prefix or suffix
\r
232 * <td>Currency sign, replaced by currency symbol. If
\r
233 * doubled, replaced by international currency symbol.
\r
234 * If tripled, replaced by currency plural names, for example,
\r
235 * "US dollar" or "US dollars" for America.
\r
236 * If present in a pattern, the monetary decimal separator
\r
237 * is used instead of the decimal separator.
\r
238 * <tr valign=top bgcolor="#eeeeff">
\r
239 * <td><code>'</code>
\r
240 * <td>Prefix or suffix
\r
242 * <td>Used to quote special characters in a prefix or suffix,
\r
243 * for example, <code>"'#'#"</code> formats 123 to
\r
244 * <code>"#123"</code>. To create a single quote
\r
245 * itself, use two in a row: <code>"# o''clock"</code>.
\r
247 * <td><code>*</code>
\r
248 * <td>Prefix or suffix boundary
\r
250 * <td>Pad escape, precedes pad character
\r
254 * <p>A <code>DecimalFormat</code> pattern contains a postive and negative
\r
255 * subpattern, for example, "#,##0.00;(#,##0.00)". Each subpattern has a
\r
256 * prefix, a numeric part, and a suffix. If there is no explicit negative
\r
257 * subpattern, the negative subpattern is the localized minus sign prefixed to the
\r
258 * positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00". If there
\r
259 * is an explicit negative subpattern, it serves only to specify the negative
\r
260 * prefix and suffix; the number of digits, minimal digits, and other
\r
261 * characteristics are ignored in the negative subpattern. That means that
\r
262 * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".
\r
264 * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
\r
265 * thousands separators, decimal separators, etc. may be set to arbitrary
\r
266 * values, and they will appear properly during formatting. However, care must
\r
267 * be taken that the symbols and strings do not conflict, or parsing will be
\r
268 * unreliable. For example, either the positive and negative prefixes or the
\r
269 * suffixes must be distinct for {@link #parse} to be able
\r
270 * to distinguish positive from negative values. Another example is that the
\r
271 * decimal separator and thousands separator should be distinct characters, or
\r
272 * parsing will be impossible.
\r
274 * <p>The <em>grouping separator</em> is a character that separates clusters of
\r
275 * integer digits to make large numbers more legible. It commonly used for
\r
276 * thousands, but in some locales it separates ten-thousands. The <em>grouping
\r
277 * size</em> is the number of digits between the grouping separators, such as 3
\r
278 * for "100,000,000" or 4 for "1 0000 0000". There are actually two different
\r
279 * grouping sizes: One used for the least significant integer digits, the
\r
280 * <em>primary grouping size</em>, and one used for all others, the
\r
281 * <em>secondary grouping size</em>. In most locales these are the same, but
\r
282 * sometimes they are different. For example, if the primary grouping interval
\r
283 * is 3, and the secondary is 2, then this corresponds to the pattern
\r
284 * "#,##,##0", and the number 123456789 is formatted as "12,34,56,789". If a
\r
285 * pattern contains multiple grouping separators, the interval between the last
\r
286 * one and the end of the integer defines the primary grouping size, and the
\r
287 * interval between the last two defines the secondary grouping size. All others
\r
288 * are ignored, so "#,##,###,####" == "###,###,####" == "##,#,###,####".
\r
290 * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
\r
291 * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException}
\r
292 * with a message that describes the problem.
\r
294 * <h4>Pattern BNF</h4>
\r
297 * pattern := subpattern (';' subpattern)?
\r
298 * subpattern := prefix? number exponent? suffix?
\r
299 * number := (integer ('.' fraction)?) | sigDigits
\r
300 * prefix := '\u0000'..'\uFFFD' - specialCharacters
\r
301 * suffix := '\u0000'..'\uFFFD' - specialCharacters
\r
302 * integer := '#'* '0'* '0'
\r
303 * fraction := '0'* '#'*
\r
304 * sigDigits := '#'* '@' '@'* '#'*
\r
305 * exponent := 'E' '+'? '0'* '0'
\r
306 * padSpec := '*' padChar
\r
307 * padChar := '\u0000'..'\uFFFD' - quote
\r
310 * X* 0 or more instances of X
\r
311 * X? 0 or 1 instances of X
\r
312 * X|Y either X or Y
\r
313 * C..D any character from C up to D, inclusive
\r
314 * S-T characters in S, except those in T
\r
316 * The first subpattern is for positive numbers. The second (optional)
\r
317 * subpattern is for negative numbers.
\r
319 * <p>Not indicated in the BNF syntax above:
\r
321 * <ul><li>The grouping separator ',' can occur inside the integer and
\r
322 * sigDigits elements, between any two pattern characters of that
\r
323 * element, as long as the integer or sigDigits element is not
\r
324 * followed by the exponent element.
\r
326 * <li>Two grouping intervals are recognized: That between the
\r
327 * decimal point and the first grouping symbol, and that
\r
328 * between the first and second grouping symbols. These
\r
329 * intervals are identical in most locales, but in some
\r
330 * locales they differ. For example, the pattern
\r
331 * "#,##,###" formats the number 123456789 as
\r
332 * "12,34,56,789".</li>
\r
335 * The pad specifier <code>padSpec</code> may appear before the prefix,
\r
336 * after the prefix, before the suffix, after the suffix, or not at all.
\r
339 * In place of '0', the digits '1' through '9' may be used to
\r
340 * indicate a rounding increment.
\r
345 * <p><code>DecimalFormat</code> parses all Unicode characters that represent
\r
346 * decimal digits, as defined by {@link UCharacter#digit}. In addition,
\r
347 * <code>DecimalFormat</code> also recognizes as digits the ten consecutive
\r
348 * characters starting with the localized zero digit defined in the
\r
349 * {@link DecimalFormatSymbols} object. During formatting, the
\r
350 * {@link DecimalFormatSymbols}-based digits are output.
\r
352 * <p>During parsing, grouping separators are ignored.
\r
354 * <p>For currency parsing, the formatter is able to parse every currency
\r
355 * style formats no matter which style the formatter is constructed with.
\r
356 * For example, a formatter instance gotten from
\r
357 * NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can parse
\r
358 * formats such as "USD1.00" and "3.00 US dollars".
\r
360 * <p>If {@link #parse(String, ParsePosition)} fails to parse
\r
361 * a string, it returns <code>null</code> and leaves the parse position
\r
362 * unchanged. The convenience method {@link #parse(String)}
\r
363 * indicates parse failure by throwing a {@link java.text.ParseException}.
\r
365 * <h4>Formatting</h4>
\r
367 * <p>Formatting is guided by several parameters, all of which can be
\r
368 * specified either using a pattern or using the API. The following
\r
369 * description applies to formats that do not use <a href="#sci">scientific
\r
370 * notation</a> or <a href="#sigdig">significant digits</a>.
\r
372 * <ul><li>If the number of actual integer digits exceeds the
\r
373 * <em>maximum integer digits</em>, then only the least significant
\r
374 * digits are shown. For example, 1997 is formatted as "97" if the
\r
375 * maximum integer digits is set to 2.
\r
377 * <li>If the number of actual integer digits is less than the
\r
378 * <em>minimum integer digits</em>, then leading zeros are added. For
\r
379 * example, 1997 is formatted as "01997" if the minimum integer digits
\r
382 * <li>If the number of actual fraction digits exceeds the <em>maximum
\r
383 * fraction digits</em>, then half-even rounding it performed to the
\r
384 * maximum fraction digits. For example, 0.125 is formatted as "0.12"
\r
385 * if the maximum fraction digits is 2. This behavior can be changed
\r
386 * by specifying a rounding increment and a rounding mode.
\r
388 * <li>If the number of actual fraction digits is less than the
\r
389 * <em>minimum fraction digits</em>, then trailing zeros are added.
\r
390 * For example, 0.125 is formatted as "0.1250" if the mimimum fraction
\r
391 * digits is set to 4.
\r
393 * <li>Trailing fractional zeros are not displayed if they occur
\r
394 * <em>j</em> positions after the decimal, where <em>j</em> is less
\r
395 * than the maximum fraction digits. For example, 0.10004 is
\r
396 * formatted as "0.1" if the maximum fraction digits is four or less.
\r
399 * <p><strong>Special Values</strong>
\r
401 * <p><code>NaN</code> is represented as a single character, typically
\r
402 * <code>\uFFFD</code>. This character is determined by the
\r
403 * {@link DecimalFormatSymbols} object. This is the only value for which
\r
404 * the prefixes and suffixes are not used.
\r
406 * <p>Infinity is represented as a single character, typically
\r
407 * <code>\u221E</code>, with the positive or negative prefixes and suffixes
\r
408 * applied. The infinity character is determined by the
\r
409 * {@link DecimalFormatSymbols} object.
\r
411 * <a name="sci"><h4>Scientific Notation</h4></a>
\r
413 * <p>Numbers in scientific notation are expressed as the product of a mantissa
\r
414 * and a power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The
\r
415 * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),
\r
416 * but it need not be. <code>DecimalFormat</code> supports arbitrary mantissas.
\r
417 * <code>DecimalFormat</code> can be instructed to use scientific
\r
418 * notation through the API or through the pattern. In a pattern, the exponent
\r
419 * character immediately followed by one or more digit characters indicates
\r
420 * scientific notation. Example: "0.###E0" formats the number 1234 as
\r
424 * <li>The number of digit characters after the exponent character gives the
\r
425 * minimum exponent digit count. There is no maximum. Negative exponents are
\r
426 * formatted using the localized minus sign, <em>not</em> the prefix and suffix
\r
427 * from the pattern. This allows patterns such as "0.###E0 m/s". To prefix
\r
428 * positive exponents with a localized plus sign, specify '+' between the
\r
429 * exponent and the digits: "0.###E+0" will produce formats "1E+1", "1E+0",
\r
430 * "1E-1", etc. (In localized patterns, use the localized plus sign rather than
\r
433 * <li>The minimum number of integer digits is achieved by adjusting the
\r
434 * exponent. Example: 0.00123 formatted with "00.###E0" yields "12.3E-4". This
\r
435 * only happens if there is no maximum number of integer digits. If there is a
\r
436 * maximum, then the minimum number of integer digits is fixed at one.
\r
438 * <li>The maximum number of integer digits, if present, specifies the exponent
\r
439 * grouping. The most common use of this is to generate <em>engineering
\r
440 * notation</em>, in which the exponent is a multiple of three, e.g.,
\r
441 * "##0.###E0". The number 12345 is formatted using "##0.####E0" as "12.345E3".
\r
443 * <li>When using scientific notation, the formatter controls the
\r
444 * digit counts using significant digits logic. The maximum number of
\r
445 * significant digits limits the total number of integer and fraction
\r
446 * digits that will be shown in the mantissa; it does not affect
\r
447 * parsing. For example, 12345 formatted with "##0.##E0" is "12.3E3".
\r
448 * See the section on significant digits for more details.
\r
450 * <li>The number of significant digits shown is determined as
\r
451 * follows: If areSignificantDigitsUsed() returns false, then the
\r
452 * minimum number of significant digits shown is one, and the maximum
\r
453 * number of significant digits shown is the sum of the <em>minimum
\r
454 * integer</em> and <em>maximum fraction</em> digits, and is
\r
455 * unaffected by the maximum integer digits. If this sum is zero,
\r
456 * then all significant digits are shown. If
\r
457 * areSignificantDigitsUsed() returns true, then the significant digit
\r
458 * counts are specified by getMinimumSignificantDigits() and
\r
459 * getMaximumSignificantDigits(). In this case, the number of
\r
460 * integer digits is fixed at one, and there is no exponent grouping.
\r
462 * <li>Exponential patterns may not contain grouping separators.
\r
465 * <a name="sigdig"><h4>
\r
466 * Significant Digits</h4></a>
\r
468 * <code>DecimalFormat</code> has two ways of controlling how many
\r
469 * digits are shows: (a) significant digits counts, or (b) integer and
\r
470 * fraction digit counts. Integer and fraction digit counts are
\r
471 * described above. When a formatter is using significant digits
\r
472 * counts, the number of integer and fraction digits is not specified
\r
473 * directly, and the formatter settings for these counts are ignored.
\r
474 * Instead, the formatter uses however many integer and fraction
\r
475 * digits are required to display the specified number of significant
\r
476 * digits. Examples:
\r
479 * <table border=0 cellspacing=3 cellpadding=0>
\r
480 * <tr bgcolor="#ccccff">
\r
481 * <th align=left>Pattern
\r
482 * <th align=left>Minimum significant digits
\r
483 * <th align=left>Maximum significant digits
\r
484 * <th align=left>Number
\r
485 * <th align=left>Output of format()
\r
487 * <td><code>@@@</code>
\r
491 * <td><code>12300</code>
\r
492 * <tr valign=top bgcolor="#eeeeff">
\r
493 * <td><code>@@@</code>
\r
497 * <td><code>0.123</code>
\r
499 * <td><code>@@##</code>
\r
503 * <td><code>3.142</code>
\r
504 * <tr valign=top bgcolor="#eeeeff">
\r
505 * <td><code>@@##</code>
\r
509 * <td><code>1.23</code>
\r
514 * <li>Significant digit counts may be expressed using patterns that
\r
515 * specify a minimum and maximum number of significant digits. These
\r
516 * are indicated by the <code>'@'</code> and <code>'#'</code>
\r
517 * characters. The minimum number of significant digits is the number
\r
518 * of <code>'@'</code> characters. The maximum number of significant
\r
519 * digits is the number of <code>'@'</code> characters plus the number
\r
520 * of <code>'#'</code> characters following on the right. For
\r
521 * example, the pattern <code>"@@@"</code> indicates exactly 3
\r
522 * significant digits. The pattern <code>"@##"</code> indicates from
\r
523 * 1 to 3 significant digits. Trailing zero digits to the right of
\r
524 * the decimal separator are suppressed after the minimum number of
\r
525 * significant digits have been shown. For example, the pattern
\r
526 * <code>"@##"</code> formats the number 0.1203 as
\r
527 * <code>"0.12"</code>.
\r
529 * <li>If a pattern uses significant digits, it may not contain a
\r
530 * decimal separator, nor the <code>'0'</code> pattern character.
\r
531 * Patterns such as <code>"@00"</code> or <code>"@.###"</code> are
\r
534 * <li>Any number of <code>'#'</code> characters may be prepended to
\r
535 * the left of the leftmost <code>'@'</code> character. These have no
\r
536 * effect on the minimum and maximum significant digits counts, but
\r
537 * may be used to position grouping separators. For example,
\r
538 * <code>"#,#@#"</code> indicates a minimum of one significant digits,
\r
539 * a maximum of two significant digits, and a grouping size of three.
\r
541 * <li>In order to enable significant digits formatting, use a pattern
\r
542 * containing the <code>'@'</code> pattern character. Alternatively,
\r
543 * call {@link #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.
\r
545 * <li>In order to disable significant digits formatting, use a
\r
546 * pattern that does not contain the <code>'@'</code> pattern
\r
547 * character. Alternatively, call {@link #setSignificantDigitsUsed
\r
548 * setSignificantDigitsUsed(false)}.
\r
550 * <li>The number of significant digits has no effect on parsing.
\r
552 * <li>Significant digits may be used together with exponential notation. Such
\r
553 * patterns are equivalent to a normal exponential pattern with a minimum and
\r
554 * maximum integer digit count of one, a minimum fraction digit count of
\r
555 * <code>getMinimumSignificantDigits() - 1</code>, and a maximum fraction digit
\r
556 * count of <code>getMaximumSignificantDigits() - 1</code>. For example, the
\r
557 * pattern <code>"@@###E0"</code> is equivalent to <code>"0.0###E0"</code>.
\r
559 * <li>If signficant digits are in use, then the integer and fraction
\r
560 * digit counts, as set via the API, are ignored. If significant
\r
561 * digits are not in use, then the signficant digit counts, as set via
\r
562 * the API, are ignored.
\r
569 * <p><code>DecimalFormat</code> supports padding the result of
\r
570 * {@link #format} to a specific width. Padding may be specified either
\r
571 * through the API or through the pattern syntax. In a pattern the pad escape
\r
572 * character, followed by a single pad character, causes padding to be parsed
\r
573 * and formatted. The pad escape character is '*' in unlocalized patterns, and
\r
574 * can be localized using {@link DecimalFormatSymbols#setPadEscape}. For
\r
575 * example, <code>"$*x#,##0.00"</code> formats 123 to <code>"$xx123.00"</code>,
\r
576 * and 1234 to <code>"$1,234.00"</code>.
\r
579 * <li>When padding is in effect, the width of the positive subpattern,
\r
580 * including prefix and suffix, determines the format width. For example, in
\r
581 * the pattern <code>"* #0 o''clock"</code>, the format width is 10.
\r
583 * <li>The width is counted in 16-bit code units (Java <code>char</code>s).
\r
585 * <li>Some parameters which usually do not matter have meaning when padding is
\r
586 * used, because the pattern width is significant with padding. In the pattern
\r
587 * "* ##,##,#,##0.##", the format width is 14. The initial characters "##,##,"
\r
588 * do not affect the grouping size or maximum integer digits, but they do affect
\r
589 * the format width.
\r
591 * <li>Padding may be inserted at one of four locations: before the prefix,
\r
592 * after the prefix, before the suffix, or after the suffix. If padding is
\r
593 * specified in any other location, {@link #applyPattern} throws an {@link
\r
594 * IllegalArgumentException}. If there is no prefix, before the
\r
595 * prefix and after the prefix are equivalent, likewise for the suffix.
\r
597 * <li>When specified in a pattern, the 16-bit <code>char</code> immediately
\r
598 * following the pad escape is the pad character. This may be any character,
\r
599 * including a special pattern character. That is, the pad escape
\r
600 * <em>escapes</em> the following character. If there is no character after
\r
601 * the pad escape, then the pattern is illegal.
\r
606 * <strong>Rounding</strong>
\r
608 * <p><code>DecimalFormat</code> supports rounding to a specific increment. For
\r
609 * example, 1230 rounded to the nearest 50 is 1250. 1.234 rounded to the
\r
610 * nearest 0.65 is 1.3. The rounding increment may be specified through the API
\r
611 * or in a pattern. To specify a rounding increment in a pattern, include the
\r
612 * increment in the pattern itself. "#,#50" specifies a rounding increment of
\r
613 * 50. "#,##0.05" specifies a rounding increment of 0.05.
\r
616 * <li>Rounding only affects the string produced by formatting. It does
\r
617 * not affect parsing or change any numerical values.
\r
619 * <li>A <em>rounding mode</em> determines how values are rounded; see the
\r
620 * {@link com.ibm.icu.math.BigDecimal} documentation for a description of the
\r
621 * modes. Rounding increments specified in patterns use the default mode,
\r
622 * {@link com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.
\r
624 * <li>Some locales use rounding in their currency formats to reflect the
\r
625 * smallest currency denomination.
\r
627 * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise
\r
628 * behave identically to digit '0'.
\r
631 * <h4>Synchronization</h4>
\r
633 * <p><code>DecimalFormat</code> objects are not synchronized. Multiple
\r
634 * threads should not access one formatter concurrently.
\r
636 * @see java.text.Format
\r
637 * @see NumberFormat
\r
638 * @author Mark Davis
\r
642 public class DecimalFormat extends NumberFormat {
\r
645 * Create a DecimalFormat using the default pattern and symbols
\r
646 * for the default locale. This is a convenient way to obtain a
\r
647 * DecimalFormat when internationalization is not the main concern.
\r
649 * To obtain standard formats for a given locale, use the factory methods
\r
650 * on NumberFormat such as getNumberInstance. These factories will
\r
651 * return the most appropriate sub-class of NumberFormat for a given
\r
653 * @see NumberFormat#getInstance
\r
654 * @see NumberFormat#getNumberInstance
\r
655 * @see NumberFormat#getCurrencyInstance
\r
656 * @see NumberFormat#getPercentInstance
\r
659 public DecimalFormat() {
\r
661 ULocale def = ULocale.getDefault();
\r
662 String pattern = getPattern(def, 0);
\r
663 // Always applyPattern after the symbols are set
\r
664 this.symbols = new DecimalFormatSymbols(def);
\r
665 setCurrency(Currency.getInstance(def));
\r
666 applyPatternWithoutExpandAffix(pattern, false);
\r
667 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
668 currencyPluralInfo = new CurrencyPluralInfo(def);
\r
669 // the exact pattern is not known until the plural count is known.
\r
670 // so, no need to expand affix now.
\r
672 expandAffixAdjustWidth(null);
\r
678 * Create a DecimalFormat from the given pattern and the symbols
\r
679 * for the default locale. This is a convenient way to obtain a
\r
680 * DecimalFormat when internationalization is not the main concern.
\r
682 * To obtain standard formats for a given locale, use the factory methods
\r
683 * on NumberFormat such as getNumberInstance. These factories will
\r
684 * return the most appropriate sub-class of NumberFormat for a given
\r
686 * @param pattern A non-localized pattern string.
\r
687 * @exception IllegalArgumentException if the given pattern is invalid.
\r
688 * @see NumberFormat#getInstance
\r
689 * @see NumberFormat#getNumberInstance
\r
690 * @see NumberFormat#getCurrencyInstance
\r
691 * @see NumberFormat#getPercentInstance
\r
694 public DecimalFormat(String pattern) {
\r
695 // Always applyPattern after the symbols are set
\r
696 ULocale def = ULocale.getDefault();
\r
697 this.symbols = new DecimalFormatSymbols(def);
\r
698 setCurrency(Currency.getInstance(def));
\r
699 applyPatternWithoutExpandAffix( pattern, false );
\r
700 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
701 currencyPluralInfo = new CurrencyPluralInfo(def);
\r
703 expandAffixAdjustWidth(null);
\r
709 * Create a DecimalFormat from the given pattern and symbols.
\r
710 * Use this constructor when you need to completely customize the
\r
711 * behavior of the format.
\r
713 * To obtain standard formats for a given
\r
714 * locale, use the factory methods on NumberFormat such as
\r
715 * getInstance or getCurrencyInstance. If you need only minor adjustments
\r
716 * to a standard format, you can modify the format returned by
\r
717 * a NumberFormat factory method.
\r
718 * @param pattern a non-localized pattern string
\r
719 * @param symbols the set of symbols to be used
\r
720 * @exception IllegalArgumentException if the given pattern is invalid
\r
721 * @see NumberFormat#getInstance
\r
722 * @see NumberFormat#getNumberInstance
\r
723 * @see NumberFormat#getCurrencyInstance
\r
724 * @see NumberFormat#getPercentInstance
\r
725 * @see DecimalFormatSymbols
\r
728 public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
\r
729 createFromPatternAndSymbols(pattern, symbols);
\r
732 private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {
\r
733 // Always applyPattern after the symbols are set
\r
734 symbols = (DecimalFormatSymbols) inputSymbols.clone();
\r
735 setCurrencyForSymbols();
\r
736 applyPatternWithoutExpandAffix(pattern, false);
\r
737 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
738 currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
\r
740 expandAffixAdjustWidth(null);
\r
746 * Create a DecimalFormat from the given pattern, symbols,
\r
747 * information used for currency plural format, and format style.
\r
748 * Use this constructor when you need to completely customize the
\r
749 * behavior of the format.
\r
751 * To obtain standard formats for a given
\r
752 * locale, use the factory methods on NumberFormat such as
\r
753 * getInstance or getCurrencyInstance.
\r
755 * If you need only minor adjustments to a standard format,
\r
756 * you can modify the format returned by
\r
757 * a NumberFormat factory method using the setters.
\r
759 * If you want to completely customize a decimal format,
\r
760 * using your own DecimalFormatSymbols (such as group separators) and
\r
761 * your own information for currency plural formatting (such as
\r
762 * plural rule and currency plural patterns), you can use this constructor.
\r
764 * @param pattern a non-localized pattern string
\r
765 * @param symbols the set of symbols to be used
\r
766 * @param infoInput the information used for currency plural format,
\r
767 * including currency plural patterns and plural rules.
\r
768 * @param style the decimal formatting style,
\r
769 * it is one of the following values:
\r
770 * NumberFormat.NUMBERSTYLE;
\r
771 * NumberFormat.CURRENCYSTYLE;
\r
772 * NumberFormat.PERCENTSTYLE;
\r
773 * NumberFormat.SCIENTIFICSTYLE;
\r
774 * NumberFormat.INTEGERSTYLE;
\r
775 * NumberFormat.ISOCURRENCYSTYLE;
\r
776 * NumberFormat.PLURALCURRENCYSTYLE;
\r
778 * @provisional This API might change or be removed in a future release.
\r
780 public DecimalFormat(String pattern, DecimalFormatSymbols symbols,
\r
781 CurrencyPluralInfo infoInput,
\r
783 CurrencyPluralInfo info = infoInput;
\r
784 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
785 info = (CurrencyPluralInfo)infoInput.clone();
\r
787 create(pattern, symbols, info, style);
\r
791 private void create(String pattern, DecimalFormatSymbols inputSymbols,
\r
792 CurrencyPluralInfo info,
\r
794 if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {
\r
795 createFromPatternAndSymbols(pattern, inputSymbols);
\r
797 // Always applyPattern after the symbols are set
\r
798 symbols = (DecimalFormatSymbols) inputSymbols.clone();
\r
799 currencyPluralInfo = info;
\r
800 // the pattern used in format is not fixed until formatting,
\r
801 // in which, the number is known and
\r
802 // will be used to pick the right pattern based on plural count.
\r
803 // Here, set the pattern as the pattern of plural count == "other".
\r
804 // For most locale, the patterns are probably the same for all
\r
805 // plural count. If not, the right pattern need to be re-applied
\r
807 String currencyPluralPatternForOther = currencyPluralInfo.getCurrencyPluralPattern("other");
\r
808 applyPatternWithoutExpandAffix(currencyPluralPatternForOther,false);
\r
809 setCurrencyForSymbols();
\r
811 style = inputStyle;
\r
816 * Create a DecimalFormat for currency plural format
\r
817 * from the given pattern, symbols, and style.
\r
819 DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {
\r
820 CurrencyPluralInfo info = null;
\r
821 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
822 info = new CurrencyPluralInfo(inputSymbols.getLocale());
\r
824 create(pattern, inputSymbols, info, style);
\r
830 public StringBuffer format(double number, StringBuffer result,
\r
831 FieldPosition fieldPosition) {
\r
832 return format(number, result, fieldPosition, false);
\r
835 // [Spark/CDL] The actual method to format number. If boolean value
\r
836 // parseAttr == true, then attribute information will be recorded.
\r
837 private StringBuffer format(double number, StringBuffer result,
\r
838 FieldPosition fieldPosition, boolean parseAttr)
\r
840 fieldPosition.setBeginIndex(0);
\r
841 fieldPosition.setEndIndex(0);
\r
843 if (Double.isNaN(number))
\r
845 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
846 fieldPosition.setBeginIndex(result.length());
\r
848 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
850 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
851 fieldPosition.setBeginIndex(result.length());
\r
855 result.append(symbols.getNaN());
\r
856 // [Spark/CDL] Add attribute for NaN here.
\r
857 // result.append(symbols.getNaN());
\r
858 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
861 addAttribute(Field.INTEGER, result.length()
\r
862 - symbols.getNaN().length(), result.length());
\r
865 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
866 fieldPosition.setEndIndex(result.length());
\r
868 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
870 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
871 fieldPosition.setEndIndex(result.length());
\r
875 addPadding(result, fieldPosition, 0, 0);
\r
879 // Do this BEFORE checking to see if value is infinite or negative!
\r
880 if (multiplier != 1) number *= multiplier;
\r
882 /* Detecting whether a double is negative is easy with the exception of
\r
883 * the value -0.0. This is a double which has a zero mantissa (and
\r
884 * exponent), but a negative sign bit. It is semantically distinct from
\r
885 * a zero with a positive sign bit, and this distinction is important
\r
886 * to certain kinds of computations. However, it's a little tricky to
\r
887 * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
\r
888 * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
\r
889 * -Infinity. Proper detection of -0.0 is needed to deal with the
\r
890 * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
\r
892 boolean isNegative = (number < 0.0) || (number == 0.0 && 1/number < 0.0);
\r
893 if (isNegative) number = -number;
\r
895 // Apply rounding after multiplier
\r
896 if (roundingDouble > 0.0) {
\r
897 // number = roundingDouble
\r
898 // * round(number / roundingDouble, roundingMode, isNegative);
\r
899 double newNumber = round(number, roundingDouble, roundingDoubleReciprocal, roundingMode, isNegative);
\r
900 if (newNumber == 0.0 && number != newNumber) isNegative = false; // if we touched it, then make zero be zero.
\r
901 number = newNumber;
\r
904 if (Double.isInfinite(number))
\r
906 int prefixLen = appendAffix(result, isNegative, true, parseAttr);
\r
908 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
909 fieldPosition.setBeginIndex(result.length());
\r
911 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
913 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
914 fieldPosition.setBeginIndex(result.length());
\r
918 // [Spark/CDL] Add attribute for infinity here.
\r
919 result.append(symbols.getInfinity());
\r
920 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
923 addAttribute(Field.INTEGER, result.length()
\r
924 - symbols.getInfinity().length(), result.length());
\r
927 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
928 fieldPosition.setEndIndex(result.length());
\r
930 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
932 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
933 fieldPosition.setEndIndex(result.length());
\r
937 int suffixLen = appendAffix(result, isNegative, false, parseAttr);
\r
939 addPadding(result, fieldPosition, prefixLen, suffixLen);
\r
943 // At this point we are guaranteed a nonnegative finite
\r
945 synchronized(digitList) {
\r
946 digitList.set(number, precision(false),
\r
947 !useExponentialNotation && !areSignificantDigitsUsed());
\r
948 return subformat(number, result, fieldPosition, isNegative, false,
\r
955 * Round a double value to the nearest multiple of the given
\r
956 * rounding increment, according to the given mode. This is
\r
957 * equivalent to rounding value/roundingInc to the nearest
\r
958 * integer, according to the given mode, and returning that
\r
959 * integer * roundingInc.
\r
960 * Note this is changed from the version in 2.4, since division of doubles
\r
961 * have inaccuracies. jitterbug 1871.
\r
962 * @param number the absolute value of the number to be rounded
\r
963 * @param roundingInc the rounding increment
\r
964 * @param roundingIncReciprocal if non-zero, is the
\r
965 * @param mode a BigDecimal rounding mode
\r
966 * @param isNegative true if the number to be rounded is negative
\r
967 * @return the absolute value of the rounded result
\r
969 private static double round(double number, double roundingInc,
\r
970 double roundingIncReciprocal, int mode, boolean isNegative) {
\r
972 double div = roundingIncReciprocal == 0.0
\r
973 ? number / roundingInc
\r
974 : number * roundingIncReciprocal;
\r
976 // do the absolute cases first
\r
979 case BigDecimal.ROUND_CEILING:
\r
980 div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));
\r
982 case BigDecimal.ROUND_FLOOR:
\r
983 div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));
\r
985 case BigDecimal.ROUND_DOWN:
\r
986 div = (Math.floor(div + epsilon));
\r
988 case BigDecimal.ROUND_UP:
\r
989 div = (Math.ceil(div - epsilon));
\r
991 case BigDecimal.ROUND_UNNECESSARY:
\r
992 if (div != Math.floor(div)) {
\r
993 throw new ArithmeticException("Rounding necessary");
\r
998 // Handle complex cases, where the choice depends on the closer value.
\r
1000 // We figure out the distances to the two possible values, ceiling and floor.
\r
1001 // We then go for the diff that is smaller.
\r
1002 // Only if they are equal does the mode matter.
\r
1004 double ceil = Math.ceil(div);
\r
1005 double ceildiff = ceil - div; // (ceil * roundingInc) - number;
\r
1006 double floor = Math.floor(div);
\r
1007 double floordiff = div - floor; // number - (floor * roundingInc);
\r
1009 // Note that the diff values were those mapped back to the "normal" space
\r
1010 // by using the roundingInc. I don't have access to the original author of the code
\r
1011 // but suspect that that was to produce better result in edge cases because of machine
\r
1012 // precision, rather than simply using the difference between, say, ceil and div.
\r
1013 // However, it didn't work in all cases. Am trying instead using an epsilon value.
\r
1016 case BigDecimal.ROUND_HALF_EVEN:
\r
1017 // We should be able to just return Math.rint(a), but this
\r
1018 // doesn't work in some VMs.
\r
1019 // if one is smaller than the other, take the corresponding side
\r
1020 if (floordiff + epsilon < ceildiff) {
\r
1022 } else if (ceildiff + epsilon < floordiff) {
\r
1024 } else { // they are equal, so we want to round to whichever is even
\r
1025 double testFloor = floor / 2;
\r
1026 div = (testFloor == Math.floor(testFloor)) ? floor : ceil;
\r
1029 case BigDecimal.ROUND_HALF_DOWN:
\r
1030 div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);
\r
1032 case BigDecimal.ROUND_HALF_UP:
\r
1033 div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);
\r
1036 throw new IllegalArgumentException("Invalid rounding mode: " + mode);
\r
1039 number = roundingIncReciprocal == 0.0
\r
1040 ? div * roundingInc
\r
1041 : div / roundingIncReciprocal;
\r
1044 private static double epsilon = 0.00000000001;
\r
1049 // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean
\r
1050 public StringBuffer format(long number, StringBuffer result,
\r
1051 FieldPosition fieldPosition) {
\r
1052 return format(number, result, fieldPosition, false);
\r
1055 private StringBuffer format(long number, StringBuffer result,
\r
1056 FieldPosition fieldPosition, boolean parseAttr)
\r
1058 fieldPosition.setBeginIndex(0);
\r
1059 fieldPosition.setEndIndex(0);
\r
1061 // If we are to do rounding, we need to move into the BigDecimal
\r
1062 // domain in order to do divide/multiply correctly.
\r
1064 if (roundingIncrementICU != null) {
\r
1065 return format(BigDecimal.valueOf(number), result, fieldPosition);
\r
1068 boolean isNegative = (number < 0);
\r
1069 if (isNegative) number = -number;
\r
1071 // In general, long values always represent real finite numbers, so
\r
1072 // we don't have to check for +/- Infinity or NaN. However, there
\r
1073 // is one case we have to be careful of: The multiplier can push
\r
1074 // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
\r
1075 // check for this before multiplying, and if it happens we use BigInteger
\r
1078 if (multiplier != 1) {
\r
1079 boolean tooBig = false;
\r
1080 if (number < 0) { // This can only happen if number == Long.MIN_VALUE
\r
1081 long cutoff = Long.MIN_VALUE / multiplier;
\r
1082 tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1
\r
1084 long cutoff = Long.MAX_VALUE / multiplier;
\r
1085 tooBig = (number > cutoff);
\r
1088 // [Spark/CDL] Use
\r
1089 // format_BigInteger_StringBuffer_FieldPosition_boolean instead
\r
1090 // parseAttr is used to judge whether to synthesize attributes.
\r
1092 BigInteger.valueOf(isNegative ? -number : number),
\r
1093 result, fieldPosition, parseAttr);
\r
1097 number *= multiplier;
\r
1098 synchronized(digitList) {
\r
1099 digitList.set(number, precision(true));
\r
1100 return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
\r
1106 * Format a BigInteger number.
\r
1110 public StringBuffer format(BigInteger number, StringBuffer result,
\r
1111 FieldPosition fieldPosition) {
\r
1112 return format(number, result, fieldPosition, false);
\r
1116 private StringBuffer format(BigInteger number, StringBuffer result,
\r
1117 FieldPosition fieldPosition, boolean parseAttr) {
\r
1118 // If we are to do rounding, we need to move into the BigDecimal
\r
1119 // domain in order to do divide/multiply correctly.
\r
1120 if (roundingIncrementICU != null) {
\r
1121 return format(new BigDecimal(number), result, fieldPosition);
\r
1124 if (multiplier != 1) {
\r
1125 number = number.multiply(BigInteger.valueOf(multiplier));
\r
1128 // At this point we are guaranteed a nonnegative finite
\r
1130 synchronized(digitList) {
\r
1131 digitList.set(number, precision(true));
\r
1132 return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true, parseAttr);
\r
1136 //#if defined(FOUNDATION10)
\r
1140 * Format a BigDecimal number.
\r
1143 public StringBuffer format(java.math.BigDecimal number, StringBuffer result,
\r
1144 FieldPosition fieldPosition) {
\r
1145 return format(number, result, fieldPosition, false);
\r
1148 private StringBuffer format(java.math.BigDecimal number,
\r
1149 StringBuffer result, FieldPosition fieldPosition, boolean parseAttr) {
\r
1150 if (multiplier != 1) {
\r
1151 number = number.multiply(java.math.BigDecimal.valueOf(multiplier));
\r
1154 if (roundingIncrement != null) {
\r
1155 number = number.divide(roundingIncrement, 0, roundingMode)
\r
1156 .multiply(roundingIncrement);
\r
1159 synchronized(digitList) {
\r
1160 digitList.set(number, precision(false),
\r
1161 !useExponentialNotation && !areSignificantDigitsUsed());
\r
1162 return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0, false, parseAttr);
\r
1169 * Format a BigDecimal number.
\r
1172 public StringBuffer format(BigDecimal number, StringBuffer result,
\r
1173 FieldPosition fieldPosition) {
\r
1174 /* This method is just a copy of the corresponding java.math.BigDecimal
\r
1175 * method for now. It isn't very efficient since it must create a
\r
1176 * conversion object to do math on the rounding increment. In the
\r
1177 * future we may try to clean this up, or even better, limit our support
\r
1178 * to just one flavor of BigDecimal.
\r
1180 if (multiplier != 1) {
\r
1181 number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);
\r
1184 if (roundingIncrementICU != null) {
\r
1185 number = number.divide(roundingIncrementICU, 0, roundingMode)
\r
1186 .multiply(roundingIncrementICU, mathContext);
\r
1189 synchronized(digitList) {
\r
1190 digitList.set(number, precision(false),
\r
1191 !useExponentialNotation && !areSignificantDigitsUsed());
\r
1192 return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0, false, false);
\r
1197 * Return true if a grouping separator belongs at the given
\r
1198 * position, based on whether grouping is in use and the values of
\r
1199 * the primary and secondary grouping interval.
\r
1200 * @param pos the number of integer digits to the right of
\r
1201 * the current position. Zero indicates the position after the
\r
1202 * rightmost integer digit.
\r
1203 * @return true if a grouping character belongs at the current
\r
1206 private boolean isGroupingPosition(int pos) {
\r
1207 boolean result = false;
\r
1208 if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {
\r
1209 if ((groupingSize2 > 0) && (pos > groupingSize)) {
\r
1210 result = ((pos - groupingSize) % groupingSize2) == 0;
\r
1212 result = pos % groupingSize == 0;
\r
1219 * Return the number of fraction digits to display, or the total
\r
1220 * number of digits for significant digit formats and exponential
\r
1223 private int precision(boolean isIntegral) {
\r
1224 if (areSignificantDigitsUsed()) {
\r
1225 return getMaximumSignificantDigits();
\r
1226 } else if (useExponentialNotation) {
\r
1227 return getMinimumIntegerDigits() + getMaximumFractionDigits();
\r
1229 return isIntegral ? 0 : getMaximumFractionDigits();
\r
1233 private StringBuffer subformat(int number, StringBuffer result,
\r
1234 FieldPosition fieldPosition,
\r
1235 boolean isNegative, boolean isInteger,
\r
1236 boolean parseAttr) {
\r
1237 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
1238 return subformat(currencyPluralInfo.select(number), result, fieldPosition,
\r
1239 isNegative, isInteger, parseAttr);
\r
1241 return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
\r
1245 private StringBuffer subformat(double number, StringBuffer result,
\r
1246 FieldPosition fieldPosition,
\r
1247 boolean isNegative, boolean isInteger,
\r
1248 boolean parseAttr) {
\r
1249 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
1250 return subformat(currencyPluralInfo.select(number), result, fieldPosition,
\r
1251 isNegative, isInteger, parseAttr);
\r
1253 return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
\r
1257 private StringBuffer subformat(String pluralCount,
\r
1258 StringBuffer result,
\r
1259 FieldPosition fieldPosition, boolean isNegative, boolean isInteger,
\r
1260 boolean parseAttr)
\r
1262 // There are 2 ways to activate currency plural format:
\r
1263 // by applying a pattern with 3 currency sign directly,
\r
1264 // or by instantiate a decimal formatter using PLURALCURRENCYSTYLE.
\r
1265 // For both cases, the number of currency sign in the pattern is 3.
\r
1266 // Even if the number of currency sign in the pattern is 3,
\r
1267 // it does not mean we need to reset the pattern.
\r
1268 // For 1st case, we do not need to reset pattern.
\r
1269 // For 2nd case, we might need to reset pattern,
\r
1270 // if the default pattern (corresponding to plural count 'other')
\r
1271 // we use is different from the pattern based on 'pluralCount'.
\r
1273 // style is only valid when decimal formatter is constructed through
\r
1274 // DecimalFormat(pattern, symbol, style)
\r
1275 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
1276 // May need to reset pattern if the style is PLURALCURRENCYSTYLE.
\r
1277 String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
\r
1278 if (formatPattern.equals(currencyPluralPattern) == false) {
\r
1279 applyPatternWithoutExpandAffix(currencyPluralPattern, false);
\r
1282 // Expand the affix to the right name according to
\r
1283 // the plural rule.
\r
1284 // This is only used for currency plural formatting.
\r
1285 // Currency plural name is not a fixed static one,
\r
1286 // it is a dynamic name based on the currency plural count.
\r
1287 // So, the affixes need to be expanded here.
\r
1288 // For other cases, the affix is a static one based on pattern alone,
\r
1289 // and it is already expanded during applying pattern,
\r
1290 // or setDecimalFormatSymbols, or setCurrency.
\r
1291 expandAffixAdjustWidth(pluralCount);
\r
1292 return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);
\r
1296 * Complete the formatting of a finite number. On entry, the digitList must
\r
1297 * be filled in with the correct digits.
\r
1299 private StringBuffer subformat(StringBuffer result,
\r
1300 FieldPosition fieldPosition, boolean isNegative, boolean isInteger,
\r
1301 boolean parseAttr)
\r
1303 // NOTE: This isn't required anymore because DigitList takes care of this.
\r
1305 // // The negative of the exponent represents the number of leading
\r
1306 // // zeros between the decimal and the first non-zero digit, for
\r
1307 // // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this
\r
1308 // // is more than the maximum fraction digits, then we have an underflow
\r
1309 // // for the printed representation. We recognize this here and set
\r
1310 // // the DigitList representation to zero in this situation.
\r
1312 // if (-digitList.decimalAt >= getMaximumFractionDigits())
\r
1314 // digitList.count = 0;
\r
1318 char zero = symbols.getZeroDigit();
\r
1319 int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
\r
1320 char grouping = currencySignCount > 0 ?
\r
1321 symbols.getMonetaryGroupingSeparator() :
\r
1322 symbols.getGroupingSeparator();
\r
1323 char decimal = currencySignCount > 0 ?
\r
1324 symbols.getMonetaryDecimalSeparator() :
\r
1325 symbols.getDecimalSeparator();
\r
1326 boolean useSigDig = areSignificantDigitsUsed();
\r
1327 int maxIntDig = getMaximumIntegerDigits();
\r
1328 int minIntDig = getMinimumIntegerDigits();
\r
1330 /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
\r
1331 * format as zero. This allows sensible computations and preserves
\r
1332 * relations such as signum(1/x) = signum(x), where x is +Infinity or
\r
1333 * -Infinity. Prior to this fix, we always formatted zero values as if
\r
1334 * they were positive. Liu 7/6/98.
\r
1336 if (digitList.isZero())
\r
1338 digitList.decimalAt = 0; // Normalize
\r
1341 int prefixLen = appendAffix(result, isNegative, true, parseAttr);
\r
1343 if (useExponentialNotation)
\r
1345 // Record field information for caller.
\r
1346 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1347 fieldPosition.setBeginIndex(result.length());
\r
1348 fieldPosition.setEndIndex(-1);
\r
1349 } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1350 fieldPosition.setBeginIndex(-1);
\r
1352 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1354 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1355 fieldPosition.setBeginIndex(result.length());
\r
1356 fieldPosition.setEndIndex(-1);
\r
1357 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1358 fieldPosition.setBeginIndex(-1);
\r
1362 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1365 // the begin index of integer part
\r
1366 // the end index of integer part
\r
1367 // the begin index of fractional part
\r
1368 int intBegin = result.length();
\r
1370 int fracBegin = -1;
\r
1373 int minFracDig = 0;
\r
1375 maxIntDig = minIntDig = 1;
\r
1376 minFracDig = getMinimumSignificantDigits() - 1;
\r
1378 minFracDig = getMinimumFractionDigits();
\r
1379 if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
\r
1381 if (maxIntDig < minIntDig) {
\r
1382 maxIntDig = minIntDig;
\r
1385 if (maxIntDig > minIntDig) {
\r
1390 // Minimum integer digits are handled in exponential format by
\r
1391 // adjusting the exponent. For example, 0.01234 with 3 minimum
\r
1392 // integer digits is "123.4E-4".
\r
1394 // Maximum integer digits are interpreted as indicating the
\r
1395 // repeating range. This is useful for engineering notation, in
\r
1396 // which the exponent is restricted to a multiple of 3. For
\r
1397 // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
\r
1398 // If maximum integer digits are defined and are larger than
\r
1399 // minimum integer digits, then minimum integer digits are
\r
1402 int exponent = digitList.decimalAt;
\r
1403 if (maxIntDig > 1 && maxIntDig != minIntDig) {
\r
1404 // A exponent increment is defined; adjust to it.
\r
1405 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig
\r
1406 : (exponent / maxIntDig) - 1;
\r
1407 exponent *= maxIntDig;
\r
1409 // No exponent increment is defined; use minimum integer digits.
\r
1410 // If none is specified, as in "#E0", generate 1 integer digit.
\r
1411 exponent -= (minIntDig > 0 || minFracDig > 0)
\r
1415 // We now output a minimum number of digits, and more if there
\r
1416 // are more digits, up to the maximum number of digits. We
\r
1417 // place the decimal point after the "integer" digits, which
\r
1418 // are the first (decimalAt - exponent) digits.
\r
1419 int minimumDigits = minIntDig + minFracDig;
\r
1420 // The number of integer digits is handled specially if the number
\r
1421 // is zero, since then there may be no digits.
\r
1422 int integerDigits = digitList.isZero() ? minIntDig :
\r
1423 digitList.decimalAt - exponent;
\r
1424 int totalDigits = digitList.count;
\r
1425 if (minimumDigits > totalDigits) totalDigits = minimumDigits;
\r
1426 if (integerDigits > totalDigits) totalDigits = integerDigits;
\r
1428 for (i=0; i<totalDigits; ++i)
\r
1430 if (i == integerDigits)
\r
1432 // Record field information for caller.
\r
1433 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1434 fieldPosition.setEndIndex(result.length());
\r
1436 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1438 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1439 fieldPosition.setEndIndex(result.length());
\r
1443 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1445 // [Spark/CDL] Add attribute for integer part
\r
1447 intEnd = result.length();
\r
1448 addAttribute(Field.INTEGER, intBegin, result.length());
\r
1451 result.append(decimal);
\r
1452 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1454 // [Spark/CDL] Add attribute for decimal separator
\r
1456 // Length of decimal separator is 1.
\r
1457 int decimalSeparatorBegin = result.length() - 1;
\r
1458 addAttribute(Field.DECIMAL_SEPARATOR,
\r
1459 decimalSeparatorBegin, result.length());
\r
1460 fracBegin = result.length();
\r
1463 // Record field information for caller.
\r
1464 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1465 fieldPosition.setBeginIndex(result.length());
\r
1467 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1469 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1470 fieldPosition.setBeginIndex(result.length());
\r
1475 result.append((i < digitList.count) ?
\r
1476 (char)(digitList.digits[i] + zeroDelta) :
\r
1480 //For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]
\r
1481 if (digitList.isZero() && (totalDigits ==0)) {
\r
1482 result.append(zero);
\r
1485 // Record field information
\r
1486 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1487 if (fieldPosition.getEndIndex() < 0) {
\r
1488 fieldPosition.setEndIndex(result.length());
\r
1490 } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1491 if (fieldPosition.getBeginIndex() < 0) {
\r
1492 fieldPosition.setBeginIndex(result.length());
\r
1494 fieldPosition.setEndIndex(result.length());
\r
1496 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1498 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1499 if (fieldPosition.getEndIndex() < 0) {
\r
1500 fieldPosition.setEndIndex(result.length());
\r
1502 } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1503 if (fieldPosition.getBeginIndex() < 0) {
\r
1504 fieldPosition.setBeginIndex(result.length());
\r
1506 fieldPosition.setEndIndex(result.length());
\r
1510 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1512 // [Spark/CDL] Calcuate the end index of integer part and fractional
\r
1513 // part if they are not properly processed yet.
\r
1516 addAttribute(Field.INTEGER, intBegin, result.length());
\r
1518 if (fracBegin > 0) {
\r
1519 addAttribute(Field.FRACTION, fracBegin, result.length());
\r
1524 // The exponent is output using the pattern-specified minimum
\r
1525 // exponent digits. There is no maximum limit to the exponent
\r
1526 // digits, since truncating the exponent would result in an
\r
1527 // unacceptable inaccuracy.
\r
1528 result.append(symbols.getExponentSeparator());
\r
1529 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1531 // [Spark/CDL] For exponent symbol, add an attribute.
\r
1533 addAttribute(Field.EXPONENT_SYMBOL, result.length()
\r
1534 - symbols.getExponentSeparator().length(), result
\r
1538 // For zero values, we force the exponent to zero. We
\r
1539 // must do this here, and not earlier, because the value
\r
1540 // is used to determine integer digit count above.
\r
1541 if (digitList.isZero()) exponent = 0;
\r
1543 boolean negativeExponent = exponent < 0;
\r
1544 if (negativeExponent) {
\r
1545 exponent = -exponent;
\r
1546 result.append(symbols.getMinusSign());
\r
1547 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1549 // [Spark/CDL] If exponent has sign, then add an exponent sign
\r
1552 // Length of exponent sign is 1.
\r
1553 addAttribute(Field.EXPONENT_SIGN, result.length() - 1,
\r
1557 } else if (exponentSignAlwaysShown) {
\r
1558 result.append(symbols.getPlusSign());
\r
1559 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1561 // [Spark/CDL] Add an plus sign attribute.
\r
1563 // Length of exponent sign is 1.
\r
1564 int expSignBegin = result.length() - 1;
\r
1565 addAttribute(Field.EXPONENT_SIGN, expSignBegin, result
\r
1570 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1572 int expBegin = result.length();
\r
1574 digitList.set(exponent);
\r
1576 int expDig = minExponentDigits;
\r
1577 if (useExponentialNotation && expDig < 1) {
\r
1580 for (i=digitList.decimalAt; i<expDig; ++i) result.append(zero);
\r
1582 for (i=0; i<digitList.decimalAt; ++i)
\r
1584 result.append((i < digitList.count) ?
\r
1585 (char)(digitList.digits[i] + zeroDelta) : zero);
\r
1587 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1589 // [Spark/CDL] Add attribute for exponent part.
\r
1591 addAttribute(Field.EXPONENT, expBegin, result.length());
\r
1597 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1599 // [Spark/CDL] Record the integer start index.
\r
1600 int intBegin = result.length();
\r
1602 // Record field information for caller.
\r
1603 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1604 fieldPosition.setBeginIndex(result.length());
\r
1606 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1608 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1609 fieldPosition.setBeginIndex(result.length());
\r
1614 int minSigDig = getMinimumSignificantDigits();
\r
1615 int maxSigDig = getMaximumSignificantDigits();
\r
1618 maxSigDig = Integer.MAX_VALUE;
\r
1621 // Output the integer portion. Here 'count' is the total
\r
1622 // number of integer digits we will display, including both
\r
1623 // leading zeros required to satisfy getMinimumIntegerDigits,
\r
1624 // and actual digits present in the number.
\r
1625 int count = useSigDig ?
\r
1626 Math.max(1, digitList.decimalAt) : minIntDig;
\r
1627 if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
\r
1628 count = digitList.decimalAt;
\r
1631 // Handle the case where getMaximumIntegerDigits() is smaller
\r
1632 // than the real number of integer digits. If this is so, we
\r
1633 // output the least significant max integer digits. For example,
\r
1634 // the value 1997 printed with 2 max integer digits is just "97".
\r
1636 int digitIndex = 0; // Index into digitList.fDigits[]
\r
1637 if (count > maxIntDig && maxIntDig >= 0) {
\r
1638 count = maxIntDig;
\r
1639 digitIndex = digitList.decimalAt - count;
\r
1642 int sizeBeforeIntegerPart = result.length();
\r
1643 for (i=count-1; i>=0; --i)
\r
1645 if (i < digitList.decimalAt && digitIndex < digitList.count &&
\r
1646 sigCount < maxSigDig) {
\r
1647 // Output a real digit
\r
1648 byte d = digitList.digits[digitIndex++];
\r
1649 result.append((char)(d + zeroDelta));
\r
1654 // Output a zero (leading or trailing)
\r
1655 result.append(zero);
\r
1656 if (sigCount > 0) {
\r
1661 // Output grouping separator if necessary.
\r
1662 if (isGroupingPosition(i)) {
\r
1663 result.append(grouping);
\r
1664 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1666 // [Spark/CDL] Add grouping separator attribute here.
\r
1668 // Length of grouping separator is 1.
\r
1669 addAttribute(Field.GROUPING_SEPARATOR,
\r
1670 result.length() - 1, result.length());
\r
1676 // Record field information for caller.
\r
1677 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
\r
1678 fieldPosition.setEndIndex(result.length());
\r
1680 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1682 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
\r
1683 fieldPosition.setEndIndex(result.length());
\r
1687 // Determine whether or not there are any printable fractional
\r
1688 // digits. If we've used up the digits we know there aren't.
\r
1689 boolean fractionPresent = (!isInteger && digitIndex < digitList.count) ||
\r
1690 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));
\r
1692 // If there is no fraction present, and we haven't printed any
\r
1693 // integer digits, then print a zero. Otherwise we won't print
\r
1694 // _any_ digits, and we won't be able to parse this string.
\r
1695 if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
\r
1696 result.append(zero);
\r
1697 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1699 // [Spark/CDL] Add attribute for integer part.
\r
1701 addAttribute(Field.INTEGER, intBegin, result.length());
\r
1704 // Output the decimal separator if we always do so.
\r
1705 if (decimalSeparatorAlwaysShown || fractionPresent)
\r
1707 result.append(decimal);
\r
1708 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1710 // [Spark/CDL] Add attribute for decimal separator
\r
1712 addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1,
\r
1718 // Record field information for caller.
\r
1719 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1720 fieldPosition.setBeginIndex(result.length());
\r
1722 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1724 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1725 fieldPosition.setBeginIndex(result.length());
\r
1729 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1731 // [Spark/CDL] Record the begin index of fraction part.
\r
1732 int fracBegin = result.length();
\r
1735 count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();
\r
1736 if (useSigDig && (sigCount == maxSigDig ||
\r
1737 (sigCount >= minSigDig && digitIndex == digitList.count))) {
\r
1740 for (i=0; i < count; ++i) {
\r
1741 // Here is where we escape from the loop. We escape
\r
1742 // if we've output the maximum fraction digits
\r
1743 // (specified in the for expression above). We also
\r
1744 // stop when we've output the minimum digits and
\r
1745 // either: we have an integer, so there is no
\r
1746 // fractional stuff to display, or we're out of
\r
1747 // significant digits.
\r
1748 if (!useSigDig && i >= getMinimumFractionDigits() &&
\r
1749 (isInteger || digitIndex >= digitList.count)) {
\r
1753 // Output leading fractional zeros. These are zeros
\r
1754 // that come after the decimal but before any
\r
1755 // significant digits. These are only output if
\r
1756 // abs(number being formatted) < 1.0.
\r
1757 if (-1-i > (digitList.decimalAt-1)) {
\r
1758 result.append(zero);
\r
1762 // Output a digit, if we have any precision left, or a
\r
1763 // zero if we don't. We don't want to output noise digits.
\r
1764 if (!isInteger && digitIndex < digitList.count) {
\r
1765 result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
\r
1767 result.append(zero);
\r
1770 // If we reach the maximum number of significant
\r
1771 // digits, or if we output all the real digits and
\r
1772 // reach the minimum, then we are done.
\r
1775 (sigCount == maxSigDig ||
\r
1776 (digitIndex == digitList.count && sigCount >= minSigDig))) {
\r
1781 // Record field information for caller.
\r
1782 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {
\r
1783 fieldPosition.setEndIndex(result.length());
\r
1785 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1787 else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {
\r
1788 fieldPosition.setEndIndex(result.length());
\r
1792 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
1794 // [Spark/CDL] Add attribute information if necessary.
\r
1795 if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {
\r
1796 addAttribute(Field.FRACTION, fracBegin, result.length());
\r
1801 int suffixLen = appendAffix(result, isNegative, false, parseAttr);
\r
1804 addPadding(result, fieldPosition, prefixLen, suffixLen);
\r
1809 private final void addPadding(StringBuffer result, FieldPosition fieldPosition,
\r
1810 int prefixLen, int suffixLen) {
\r
1811 if (formatWidth > 0) {
\r
1812 int len = formatWidth - result.length();
\r
1814 char[] padding = new char[len];
\r
1815 for (int i=0; i<len; ++i) {
\r
1818 switch (padPosition) {
\r
1819 case PAD_AFTER_PREFIX:
\r
1820 result.insert(prefixLen, padding);
\r
1822 case PAD_BEFORE_PREFIX:
\r
1823 result.insert(0, padding);
\r
1825 case PAD_BEFORE_SUFFIX:
\r
1826 result.insert(result.length() - suffixLen, padding);
\r
1828 case PAD_AFTER_SUFFIX:
\r
1829 result.append(padding);
\r
1832 if (padPosition == PAD_BEFORE_PREFIX ||
\r
1833 padPosition == PAD_AFTER_PREFIX) {
\r
1834 fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);
\r
1835 fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);
\r
1843 * Parse the given string, returning a <code>Number</code> object to
\r
1844 * represent the parsed value. <code>Double</code> objects are returned to
\r
1845 * represent non-integral values which cannot be stored in a
\r
1846 * <code>BigDecimal</code>. These are <code>NaN</code>, infinity,
\r
1847 * -infinity, and -0.0. If {@link #isParseBigDecimal()} is false (the
\r
1848 * default), all other values are returned as <code>Long</code>,
\r
1849 * <code>BigInteger</code>, or <code>BigDecimal</code> values,
\r
1850 * in that order of preference. If {@link #isParseBigDecimal()} is true,
\r
1851 * all other values are returned as <code>BigDecimal</code> valuse.
\r
1852 * If the parse fails, null is returned.
\r
1853 * @param text the string to be parsed
\r
1854 * @param parsePosition defines the position where parsing is to begin,
\r
1855 * and upon return, the position where parsing left off. If the position
\r
1856 * has not changed upon return, then parsing failed.
\r
1857 * @return a <code>Number</code> object with the parsed value or
\r
1858 * <code>null</code> if the parse failed
\r
1861 public Number parse(String text, ParsePosition parsePosition) {
\r
1862 return (Number) parse(text, parsePosition, false);
\r
1867 * Parses text from the given string as a CurrencyAmount. Unlike
\r
1868 * the parse() method, this method will attempt to parse a generic
\r
1869 * currency name, searching for a match of this object's locale's
\r
1870 * currency display names, or for a 3-letter ISO currency code.
\r
1871 * This method will fail if this format is not a currency format,
\r
1872 * that is, if it does not contain the currency pattern symbol
\r
1873 * (U+00A4) in its prefix or suffix.
\r
1875 * @param text the string to parse
\r
1876 * @param pos input-output position; on input, the position within
\r
1877 * text to match; must have 0 <= pos.getIndex() < text.length();
\r
1878 * on output, the position after the last matched character. If
\r
1879 * the parse fails, the position in unchanged upon output.
\r
1880 * @return a CurrencyAmount, or null upon failure
\r
1882 * @deprecated This API is ICU internal only.
\r
1884 CurrencyAmount parseCurrency(String text, ParsePosition pos) {
\r
1885 return (CurrencyAmount) parse(text, pos, true);
\r
1889 * Parses the given text as either a Number or a CurrencyAmount.
\r
1890 * @param text the string to parse
\r
1891 * @param parsePosition input-output position; on input, the
\r
1892 * position within text to match; must have 0 <= pos.getIndex() <
\r
1893 * text.length(); on output, the position after the last matched
\r
1894 * character. If the parse fails, the position in unchanged upon
\r
1896 * @param parseCurrency if true, a CurrencyAmount is parsed and
\r
1897 * returned; otherwise a Number is parsed and returned
\r
1898 * @return a Number or CurrencyAmount or null
\r
1900 private Object parse(String text, ParsePosition parsePosition, boolean parseCurrency) {
\r
1902 int i = backup = parsePosition.getIndex();
\r
1904 // Handle NaN as a special case:
\r
1906 // Skip padding characters, if around prefix
\r
1907 if (formatWidth > 0 && (padPosition == PAD_BEFORE_PREFIX ||
\r
1908 padPosition == PAD_AFTER_PREFIX)) {
\r
1909 i = skipPadding(text, i);
\r
1911 if (text.regionMatches(i, symbols.getNaN(),
\r
1912 0, symbols.getNaN().length())) {
\r
1913 i += symbols.getNaN().length();
\r
1914 // Skip padding characters, if around suffix
\r
1915 if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||
\r
1916 padPosition == PAD_AFTER_SUFFIX)) {
\r
1917 i = skipPadding(text, i);
\r
1919 parsePosition.setIndex(i);
\r
1920 return new Double(Double.NaN);
\r
1923 // NaN parse failed; start over
\r
1926 boolean[] status = new boolean[STATUS_LENGTH];
\r
1927 Currency[] currency = parseCurrency ? new Currency[1] : null;
\r
1928 if (currencySignCount > 0) {
\r
1929 if (!parseForCurrency(text, parsePosition, parseCurrency,
\r
1930 currency, status)) {
\r
1934 if (!subparse(text, parsePosition, digitList, false, status,
\r
1935 currency, negPrefixPattern, negSuffixPattern,
\r
1936 posPrefixPattern, posSuffixPattern, Currency.SYMBOL_NAME)) {
\r
1937 parsePosition.setIndex(backup);
\r
1944 // Handle infinity
\r
1945 if (status[STATUS_INFINITE]) {
\r
1946 n = new Double(status[STATUS_POSITIVE]
\r
1947 ? Double.POSITIVE_INFINITY
\r
1948 : Double.NEGATIVE_INFINITY);
\r
1951 // Handle underflow
\r
1952 else if (status[STATUS_UNDERFLOW]) {
\r
1953 n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");
\r
1957 else if (!status[STATUS_POSITIVE] && digitList.isZero()) {
\r
1958 n = new Double("-0.0");
\r
1962 // Do as much of the multiplier conversion as possible without
\r
1963 // losing accuracy.
\r
1964 int mult = multiplier; // Don't modify this.multiplier
\r
1965 while (mult % 10 == 0) {
\r
1966 --digitList.decimalAt;
\r
1970 // Handle integral values
\r
1971 if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {
\r
1972 // hack quick long
\r
1973 if (digitList.decimalAt < 12) { // quick check for long
\r
1975 if (digitList.count > 0) {
\r
1977 while (nx < digitList.count) {
\r
1978 l = l * 10 + (char)digitList.digits[nx++] - '0';
\r
1980 while (nx++ < digitList.decimalAt) {
\r
1983 if (!status[STATUS_POSITIVE]) {
\r
1989 BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);
\r
1990 n = (big.bitLength() < 64) ?
\r
1991 (Number) new Long(big.longValue()) : (Number) big;
\r
1994 // Handle non-integral values or the case where parseBigDecimal is set
\r
1996 BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);
\r
1999 n = big.divide(BigDecimal.valueOf(mult), mathContext);
\r
2004 // Assemble into CurrencyAmount if necessary
\r
2005 return parseCurrency ? (Object) new CurrencyAmount(n, currency[0])
\r
2010 private boolean parseForCurrency(String text, ParsePosition parsePosition,
\r
2011 boolean parseCurrency, Currency[] currency,
\r
2012 boolean[] status) {
\r
2013 int origPos = parsePosition.getIndex();
\r
2014 if (!isReadyForParsing) {
\r
2015 int savedCurrencySignCount = currencySignCount;
\r
2016 setupCurrencyAffixForAllPatterns();
\r
2017 // reset pattern back
\r
2018 if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {
\r
2019 applyPatternWithoutExpandAffix(formatPattern, false);
\r
2021 applyPattern(formatPattern, false);
\r
2023 isReadyForParsing = true;
\r
2025 int maxPosIndex = origPos;
\r
2026 int maxErrorPos = -1;
\r
2027 boolean[] savedStatus = null;
\r
2028 // First, parse against current pattern.
\r
2029 // Since current pattern could be set by applyPattern(),
\r
2030 // it could be an arbitrary pattern, and it may not be the one
\r
2031 // defined in current locale.
\r
2032 boolean[] tmpStatus = new boolean[STATUS_LENGTH];
\r
2033 ParsePosition tmpPos = new ParsePosition(origPos);
\r
2034 DigitList tmpDigitList = new DigitList();
\r
2036 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
2037 found = subparse(text, tmpPos, tmpDigitList, false,
\r
2038 tmpStatus, currency, negPrefixPattern, negSuffixPattern,
\r
2039 posPrefixPattern, posSuffixPattern, Currency.LONG_NAME);
\r
2041 found = subparse(text, tmpPos, tmpDigitList, false,
\r
2042 tmpStatus, currency, negPrefixPattern, negSuffixPattern,
\r
2043 posPrefixPattern, posSuffixPattern, Currency.SYMBOL_NAME);
\r
2046 if (tmpPos.getIndex() > maxPosIndex) {
\r
2047 maxPosIndex = tmpPos.getIndex();
\r
2048 savedStatus = tmpStatus;
\r
2049 digitList = tmpDigitList;
\r
2052 maxErrorPos = tmpPos.getErrorIndex();
\r
2054 // Then, parse against affix patterns.
\r
2055 // Those are currency patterns and currency plural patterns
\r
2056 // defined in the locale.
\r
2057 Iterator iter = affixPatternsForCurrency.iterator();
\r
2058 while (iter.hasNext()) {
\r
2059 AffixForCurrency affix = (AffixForCurrency)iter.next();
\r
2061 tmpStatus = new boolean[STATUS_LENGTH];
\r
2062 tmpPos = new ParsePosition(origPos);
\r
2063 tmpDigitList = new DigitList();
\r
2064 boolean result = subparse(text, tmpPos, tmpDigitList, false,
\r
2065 tmpStatus, currency, affix.getNegPrefix(),
\r
2066 affix.getNegSuffix(), affix.getPosPrefix(),
\r
2067 affix.getPosSuffix(), affix.getPatternType());
\r
2070 if (tmpPos.getIndex() > maxPosIndex) {
\r
2071 maxPosIndex = tmpPos.getIndex();
\r
2072 savedStatus = tmpStatus;
\r
2073 digitList = tmpDigitList;
\r
2076 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
\r
2077 tmpPos.getErrorIndex() : maxErrorPos;
\r
2080 // Finally, parse against simple affix to find the match.
\r
2081 // For example, in TestMonster suite,
\r
2082 // if the to-be-parsed text is "-\u00A40,00".
\r
2083 // complexAffixCompare will not find match,
\r
2084 // since there is no ISO code matches "\u00A4",
\r
2085 // and the parse stops at "\u00A4".
\r
2086 // We will just use simple affix comparison (look for exact match)
\r
2088 tmpStatus = new boolean[STATUS_LENGTH];
\r
2089 tmpPos = new ParsePosition(origPos);
\r
2090 tmpDigitList = new DigitList();
\r
2091 int savedCurrencySignCount = currencySignCount;
\r
2092 // set currencySignCount to 0 so that compareAffix function will
\r
2093 // fall to compareSimpleAffix path, not compareComplexAffix path.
\r
2094 currencySignCount = 0;
\r
2095 boolean result = subparse(text, tmpPos, tmpDigitList, false,
\r
2096 tmpStatus, currency, negativePrefix, negativeSuffix,
\r
2097 positivePrefix, positiveSuffix, Currency.SYMBOL_NAME);
\r
2098 currencySignCount = savedCurrencySignCount;
\r
2100 if (tmpPos.getIndex() > maxPosIndex) {
\r
2101 maxPosIndex = tmpPos.getIndex();
\r
2102 savedStatus = tmpStatus;
\r
2103 digitList = tmpDigitList;
\r
2107 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ?
\r
2108 tmpPos.getErrorIndex() : maxErrorPos;
\r
2112 //parsePosition.setIndex(origPos);
\r
2113 parsePosition.setErrorIndex(maxErrorPos);
\r
2115 parsePosition.setIndex(maxPosIndex);
\r
2116 parsePosition.setErrorIndex(-1);
\r
2117 for (int index = 0; index < STATUS_LENGTH; ++index) {
\r
2118 status[index] = savedStatus[index];
\r
2125 // Get affix patterns used in locale's currency pattern
\r
2126 // (NumberPatterns[1]) and currency plural pattern (CurrencyUnitPatterns).
\r
2127 private void setupCurrencyAffixForAllPatterns() {
\r
2128 if (currencyPluralInfo == null) {
\r
2129 currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
\r
2131 affixPatternsForCurrency = new HashSet();
\r
2133 // save the current pattern, since it will be changed by
\r
2134 // applyPatternWithoutExpandAffix
\r
2135 String savedFormatPattern = formatPattern;
\r
2137 // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same
\r
2138 // prefix and suffix, so, only need to save one of them.
\r
2139 // Here, chose onlyApplyPatternWithoutExpandAffix without
\r
2140 // saving the actualy pattern in 'pattern' data member.
\r
2141 // TODO: is it uloc?
\r
2142 applyPatternWithoutExpandAffix(getPattern(symbols.getLocale(), NumberFormat.CURRENCYSTYLE), false);
\r
2143 AffixForCurrency affixes = new AffixForCurrency(negPrefixPattern,
\r
2147 Currency.SYMBOL_NAME);
\r
2148 affixPatternsForCurrency.add(affixes);
\r
2150 // add plural pattern
\r
2151 Iterator iter = currencyPluralInfo.pluralPatternIterator();
\r
2152 Set currencyUnitPatternSet = new HashSet();
\r
2153 while (iter.hasNext()) {
\r
2154 String pluralCount = (String)iter.next();
\r
2155 String currencyPattern = (String)currencyPluralInfo.getCurrencyPluralPattern(pluralCount);
\r
2156 if (currencyPattern != null &&
\r
2157 currencyUnitPatternSet.contains(currencyPattern) == false) {
\r
2158 currencyUnitPatternSet.add(currencyPattern);
\r
2159 applyPatternWithoutExpandAffix(currencyPattern, false);
\r
2160 affixes = new AffixForCurrency(negPrefixPattern,
\r
2164 Currency.LONG_NAME);
\r
2165 affixPatternsForCurrency.add(affixes);
\r
2168 // reset pattern back
\r
2169 formatPattern = savedFormatPattern;
\r
2172 private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;
\r
2173 private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;
\r
2174 private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;
\r
2176 private static final int STATUS_INFINITE = 0;
\r
2177 private static final int STATUS_POSITIVE = 1;
\r
2178 private static final int STATUS_UNDERFLOW = 2;
\r
2179 private static final int STATUS_LENGTH = 3;
\r
2180 private static final UnicodeSet dotEquivalents =(UnicodeSet) new UnicodeSet(
\r
2181 "[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]").freeze();
\r
2182 private static final UnicodeSet commaEquivalents = (UnicodeSet) new UnicodeSet(
\r
2183 "[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]").freeze();
\r
2184 private static final UnicodeSet otherGroupingSeparators = (UnicodeSet) new UnicodeSet(
\r
2185 "[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]").freeze();
\r
2187 private static final UnicodeSet strictDotEquivalents =(UnicodeSet) new UnicodeSet(
\r
2188 "[.\u2024\uFE52\uFF0E\uFF61]").freeze();
\r
2189 private static final UnicodeSet strictCommaEquivalents = (UnicodeSet) new UnicodeSet(
\r
2190 "[,\u066B\uFE10\uFE50\uFF0C]").freeze();
\r
2191 private static final UnicodeSet strictOtherGroupingSeparators = (UnicodeSet) new UnicodeSet(
\r
2192 "[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]").freeze();
\r
2194 private static final UnicodeSet defaultGroupingSeparators = (UnicodeSet) new UnicodeSet(
\r
2195 dotEquivalents).addAll(commaEquivalents).addAll(otherGroupingSeparators).freeze();
\r
2196 private static final UnicodeSet strictDefaultGroupingSeparators = (UnicodeSet) new UnicodeSet(
\r
2197 strictDotEquivalents).addAll(strictCommaEquivalents).addAll(strictOtherGroupingSeparators).freeze();
\r
2199 // When parsing a number with big exponential value, it requires to transform
\r
2200 // the value into a string representation to construct BigInteger instance.
\r
2201 // We want to set the maximum size because it can easily trigger OutOfMemoryException.
\r
2202 // PARSE_MAX_EXPONENT is currently set to 1000, which is much bigger than
\r
2203 // MAX_VALUE of Double (
\r
2204 // See the problem reported by ticket#5698
\r
2205 private static final int PARSE_MAX_EXPONENT = 1000;
\r
2208 * <strong><font face=helvetica color=red>CHANGED</font></strong>
\r
2209 * Parse the given text into a number. The text is parsed beginning at
\r
2210 * parsePosition, until an unparseable character is seen.
\r
2211 * @param text The string to parse.
\r
2212 * @param parsePosition The position at which to being parsing. Upon
\r
2213 * return, the first unparseable character.
\r
2214 * @param digits The DigitList to set to the parsed value.
\r
2215 * @param isExponent If true, parse an exponent. This means no
\r
2216 * infinite values and integer only.
\r
2217 * @param status Upon return contains boolean status flags indicating
\r
2218 * whether the value was infinite and whether it was positive.
\r
2219 * @param currency return value for parsed currency, for generic
\r
2220 * currency parsing mode, or null for normal parsing. In generic
\r
2221 * currency parsing mode, any currency is parsed, not just the
\r
2222 * currency that this formatter is set to.
\r
2223 * @param negPrefix negative prefix pattern
\r
2224 * @param negSuffix negative suffix pattern
\r
2225 * @param posPrefix positive prefix pattern
\r
2226 * @param negSuffix negative suffix pattern
\r
2227 * @param type type of currency to parse against, LONG_NAME only or not.
\r
2229 private final boolean subparse(String text, ParsePosition parsePosition,
\r
2230 DigitList digits, boolean isExponent,
\r
2231 boolean status[], Currency currency[],
\r
2232 String negPrefix, String negSuffix,
\r
2233 String posPrefix, String posSuffix,
\r
2236 int position = parsePosition.getIndex();
\r
2237 int oldStart = parsePosition.getIndex();
\r
2239 // Match padding before prefix
\r
2240 if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {
\r
2241 position = skipPadding(text, position);
\r
2244 // Match positive and negative prefixes; prefer longest match.
\r
2245 int posMatch = compareAffix(text, position, false, true, posPrefix, type, currency);
\r
2246 int negMatch = compareAffix(text, position, true, true, negPrefix, type, currency);
\r
2247 if (posMatch >= 0 && negMatch >= 0) {
\r
2248 if (posMatch > negMatch) {
\r
2250 } else if (negMatch > posMatch) {
\r
2254 if (posMatch >= 0) {
\r
2255 position += posMatch;
\r
2256 } else if (negMatch >= 0) {
\r
2257 position += negMatch;
\r
2259 parsePosition.setErrorIndex(position);
\r
2263 // Match padding after prefix
\r
2264 if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {
\r
2265 position = skipPadding(text, position);
\r
2268 // process digits or Inf, find decimal position
\r
2269 status[STATUS_INFINITE] = false;
\r
2270 if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
\r
2271 symbols.getInfinity().length()))
\r
2273 position += symbols.getInfinity().length();
\r
2274 status[STATUS_INFINITE] = true;
\r
2276 // We now have a string of digits, possibly with grouping symbols,
\r
2277 // and decimal points. We want to process these into a DigitList.
\r
2278 // We don't want to put a bunch of leading zeros into the DigitList
\r
2279 // though, so we keep track of the location of the decimal point,
\r
2280 // put only significant digits into the DigitList, and adjust the
\r
2281 // exponent as needed.
\r
2283 digits.decimalAt = digits.count = 0;
\r
2284 char zero = symbols.getZeroDigit();
\r
2285 char decimal = currencySignCount > 0 ?
\r
2286 symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator();
\r
2287 char grouping = symbols.getGroupingSeparator();
\r
2289 String exponentSep = symbols.getExponentSeparator();
\r
2290 boolean sawDecimal = false;
\r
2291 boolean sawExponent = false;
\r
2292 boolean sawDigit = false;
\r
2293 long exponent = 0; // Set to the exponent value, if any
\r
2297 boolean strictParse = isParseStrict();
\r
2298 boolean strictFail = false; // did we exit with a strict parse failure?
\r
2299 int lastGroup = -1; // where did we last see a grouping separator?
\r
2300 int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
\r
2302 // Strict parsing leading zeroes. If a leading zero would
\r
2303 // be forced by the pattern, then don't fail strict parsing.
\r
2304 boolean strictLeadingZero = false;
\r
2305 int leadingZeroPos = 0;
\r
2306 int leadingZeroCount = 0;
\r
2308 // equivalent grouping and decimal support
\r
2310 // TODO markdavis Cache these if it makes a difference in performance.
\r
2311 UnicodeSet decimalSet = new UnicodeSet(getSimilarDecimals(decimal, strictParse));
\r
2312 UnicodeSet groupingSet = new UnicodeSet(strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators)
\r
2313 .add(grouping).removeAll(decimalSet);
\r
2315 // we are guaranteed that
\r
2316 // decimalSet contains the decimal, and
\r
2317 // groupingSet contains the groupingSeparator
\r
2318 // (unless decimal and grouping are the same, which should never happen. But in that case, groupingSet will just be empty.)
\r
2321 // We have to track digitCount ourselves, because digits.count will
\r
2322 // pin when the maximum allowable digits is reached.
\r
2323 int digitCount = 0;
\r
2326 for (; position < text.length(); ++position)
\r
2328 char ch = text.charAt(position);
\r
2330 /* We recognize all digit ranges, not only the Latin digit range
\r
2331 * '0'..'9'. We do so by using the UCharacter.digit() method,
\r
2332 * which converts a valid Unicode digit to the range 0..9.
\r
2334 * The character 'ch' may be a digit. If so, place its value
\r
2335 * from 0 to 9 in 'digit'. First try using the locale digit,
\r
2336 * which may or MAY NOT be a standard Unicode digit range. If
\r
2337 * this fails, try using the standard Unicode digit ranges by
\r
2338 * calling UCharacter.digit(). If this also fails, digit will
\r
2339 * have a value outside the range 0..9.
\r
2341 digit = ch - zero;
\r
2342 if (digit < 0 || digit > 9) digit = UCharacter.digit(ch, 10);
\r
2346 // Cancel out backup setting (see grouping handler below)
\r
2347 if (strictParse && backup != -1) {
\r
2348 // comma followed by digit, so group before comma is a
\r
2349 // secondary group. If there was a group separator
\r
2350 // before that, the group must == the secondary group
\r
2351 // length, else it can be <= the the secondary group
\r
2353 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
\r
2354 (lastGroup == -1 && position - oldStart - 1 > gs2)) {
\r
2355 strictFail = true;
\r
2358 lastGroup = backup;
\r
2360 backup = -1; // Do this BEFORE continue statement below!!!
\r
2363 // Handle leading zeros
\r
2364 if (digits.count == 0)
\r
2366 if (!sawDecimal) {
\r
2367 if (strictParse && !isExponent) {
\r
2368 // Allow leading zeros in exponents
\r
2369 // Count leading zeros for checking later
\r
2370 if (!strictLeadingZero) leadingZeroPos = position + 1;
\r
2371 strictLeadingZero = true;
\r
2372 ++leadingZeroCount;
\r
2374 // Ignore leading zeros in integer part of number.
\r
2378 // If we have seen the decimal, but no significant digits yet,
\r
2379 // then we account for leading zeros by decrementing the
\r
2380 // digits.decimalAt into negative values.
\r
2381 --digits.decimalAt;
\r
2386 digits.append((char)(digit + '0'));
\r
2389 else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
\r
2391 if (strictParse) {
\r
2392 if (backup != -1) {
\r
2393 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) ||
\r
2394 (lastGroup == -1 && position - oldStart - 1 > gs2)) {
\r
2395 strictFail = true;
\r
2398 lastGroup = backup;
\r
2404 digits.append((char)(digit + '0'));
\r
2406 // Cancel out backup setting (see grouping handler below)
\r
2409 else if (!isExponent && decimalSet.contains(ch))
\r
2411 if (strictParse) {
\r
2412 if (backup != -1 ||
\r
2413 (lastGroup != -1 && position - lastGroup != groupingSize + 1)) {
\r
2414 strictFail = true;
\r
2418 // If we're only parsing integers, or if we ALREADY saw the
\r
2419 // decimal, then don't parse this one.
\r
2420 if (isParseIntegerOnly() || sawDecimal) break;
\r
2421 digits.decimalAt = digitCount; // Not digits.count!
\r
2422 sawDecimal = true;
\r
2424 // Once we see a decimal character, we only accept that decimal character from then on.
\r
2425 decimalSet.set(ch,ch);
\r
2427 else if (!isExponent && isGroupingUsed() && groupingSet.contains(ch))
\r
2432 if (strictParse) {
\r
2433 if ((!sawDigit || backup != -1)) {
\r
2434 // leading group, or two group separators in a row
\r
2435 strictFail = true;
\r
2439 // Once we see a grouping character, we only accept that grouping character from then on.
\r
2440 groupingSet.set(ch,ch);
\r
2442 // Ignore grouping characters, if we are using them, but require
\r
2443 // that they be followed by a digit. Otherwise we backup and
\r
2444 // reprocess them.
\r
2445 backup = position;
\r
2447 else if (!isExponent && !sawExponent &&
\r
2448 text.regionMatches(position, exponentSep,
\r
2449 0, exponentSep.length()))
\r
2451 // Parse sign, if present
\r
2452 boolean negExp = false;
\r
2453 int pos = position + exponentSep.length();
\r
2454 if (pos < text.length()) {
\r
2455 ch = text.charAt(pos);
\r
2456 if (ch == symbols.getPlusSign()) {
\r
2458 } else if (ch == symbols.getMinusSign()) {
\r
2464 DigitList exponentDigits = new DigitList();
\r
2465 exponentDigits.count = 0;
\r
2466 while (pos < text.length()) {
\r
2467 digit = text.charAt(pos) - zero;
\r
2468 if (digit < 0 || digit > 9) {
\r
2470 Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
\r
2471 Should update reassign the value of 'ch' in the
\r
2472 code: digit = Character.digit(ch, 10);
\r
2475 digit = UCharacter.digit(text.charAt(pos), 10);
\r
2477 if (digit >= 0 && digit <= 9) {
\r
2478 exponentDigits.append((char)(digit + '0'));
\r
2485 if (exponentDigits.count > 0) {
\r
2486 // defer strict parse until we know we have a bona-fide exponent
\r
2487 if (strictParse) {
\r
2488 if (backup != -1 || lastGroup != -1) {
\r
2489 strictFail = true;
\r
2494 // Quick overflow check for exponential part.
\r
2495 // Actual limit check will be done later in this code.
\r
2496 if (exponentDigits.count > 10 /* maximum decimal digits for int */) {
\r
2498 // set underflow flag
\r
2499 status[STATUS_UNDERFLOW] = true;
\r
2501 // set infinite flag
\r
2502 status[STATUS_INFINITE] = true;
\r
2505 exponentDigits.decimalAt = exponentDigits.count;
\r
2506 exponent = exponentDigits.getLong();
\r
2508 exponent = -exponent;
\r
2511 position = pos; // Advance past the exponent
\r
2512 sawExponent = true;
\r
2515 break; // Whether we fail or succeed, we exit this loop
\r
2520 if (backup != -1) position = backup;
\r
2522 // If there was no decimal point we have an integer
\r
2523 if (!sawDecimal) digits.decimalAt = digitCount; // Not digits.count!
\r
2525 // check for strict parse errors
\r
2526 if (strictParse && strictLeadingZero) {
\r
2527 if ((leadingZeroCount + digits.decimalAt) > this.getMinimumIntegerDigits()) {
\r
2528 parsePosition.setIndex(oldStart);
\r
2529 parsePosition.setErrorIndex(leadingZeroPos);
\r
2533 if (strictParse && !sawDecimal) {
\r
2534 if (lastGroup != -1 && position - lastGroup != groupingSize + 1) {
\r
2535 strictFail = true;
\r
2539 // only set with strictParse and a leading zero error
\r
2540 // leading zeros are an error with strict parsing except
\r
2541 // immediately before nondigit (except group separator
\r
2542 // followed by digit), or end of text.
\r
2544 parsePosition.setIndex(oldStart);
\r
2545 parsePosition.setErrorIndex(position);
\r
2549 // Adjust for exponent, if any
\r
2550 exponent += digits.decimalAt;
\r
2551 if (exponent < -PARSE_MAX_EXPONENT) {
\r
2552 status[STATUS_UNDERFLOW] = true;
\r
2553 } else if (exponent > PARSE_MAX_EXPONENT) {
\r
2554 status[STATUS_INFINITE] = true;
\r
2556 digits.decimalAt = (int)exponent;
\r
2559 // If none of the text string was recognized. For example, parse
\r
2560 // "x" with pattern "#0.00" (return index and error index both 0)
\r
2561 // parse "$" with pattern "$#0.00". (return index 0 and error index
\r
2563 if (!sawDigit && digitCount == 0) {
\r
2564 parsePosition.setIndex(oldStart);
\r
2565 parsePosition.setErrorIndex(oldStart);
\r
2570 // Match padding before suffix
\r
2571 if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {
\r
2572 position = skipPadding(text, position);
\r
2575 // Match positive and negative suffixes; prefer longest match.
\r
2576 if (posMatch >= 0) {
\r
2577 posMatch = compareAffix(text, position, false, false, posSuffix, type, currency);
\r
2579 if (negMatch >= 0) {
\r
2580 negMatch = compareAffix(text, position, true, false, negSuffix, type, currency);
\r
2582 if (posMatch >= 0 && negMatch >= 0) {
\r
2583 if (posMatch > negMatch) {
\r
2585 } else if (negMatch > posMatch) {
\r
2590 // Fail if neither or both
\r
2591 if ((posMatch >= 0) == (negMatch >= 0)) {
\r
2592 parsePosition.setErrorIndex(position);
\r
2596 position += (posMatch>=0 ? posMatch : negMatch);
\r
2598 // Match padding after suffix
\r
2599 if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {
\r
2600 position = skipPadding(text, position);
\r
2603 parsePosition.setIndex(position);
\r
2605 status[STATUS_POSITIVE] = (posMatch >= 0);
\r
2607 if (parsePosition.getIndex() == oldStart) {
\r
2608 parsePosition.setErrorIndex(position);
\r
2615 * Return characters that are used where this decimal is used.
\r
2617 * @param strictParse
\r
2620 private UnicodeSet getSimilarDecimals(char decimal, boolean strictParse) {
\r
2621 if (dotEquivalents.contains(decimal)) {
\r
2622 return strictParse ? strictDotEquivalents : dotEquivalents;
\r
2624 if (commaEquivalents.contains(decimal)) {
\r
2625 return strictParse ? strictCommaEquivalents : commaEquivalents;
\r
2627 // if there is no match, return the character itself
\r
2628 return new UnicodeSet().add(decimal);
\r
2632 * Starting at position, advance past a run of pad characters, if any.
\r
2633 * Return the index of the first character after position that is not a pad
\r
2634 * character. Result is >= position.
\r
2636 private final int skipPadding(String text, int position) {
\r
2637 while (position < text.length() && text.charAt(position) == pad) {
\r
2644 * Return the length matched by the given affix, or -1 if none.
\r
2645 * Runs of white space in the affix, match runs of white space in
\r
2646 * the input. Pattern white space and input white space are
\r
2647 * determined differently; see code.
\r
2648 * @param text input text
\r
2649 * @param pos offset into input at which to begin matching
\r
2650 * @param isNegative
\r
2652 * @param affixPat affix pattern used for currency affix comparison
\r
2653 * @param type compare against currency type, LONG_NAME only or not.
\r
2654 * @param currency return value for parsed currency, for generic
\r
2655 * currency parsing mode, or null for normal parsing. In generic
\r
2656 * currency parsing mode, any currency is parsed, not just the
\r
2657 * currency that this formatter is set to.
\r
2658 * @return length of input that matches, or -1 if match failure
\r
2660 private int compareAffix(String text, int pos,
\r
2661 boolean isNegative, boolean isPrefix,
\r
2664 Currency[] currency) {
\r
2665 if (currency != null || currencyChoice != null ||
\r
2666 currencySignCount > 0) {
\r
2667 return compareComplexAffix(affixPat, text, pos, type, currency);
\r
2670 return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix,
\r
2673 return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix,
\r
2682 * Return the length matched by the given affix, or -1 if none.
\r
2683 * Runs of white space in the affix, match runs of white space in
\r
2684 * the input. Pattern white space and input white space are
\r
2685 * determined differently; see code.
\r
2686 * @param affix pattern string, taken as a literal
\r
2687 * @param input input text
\r
2688 * @param pos offset into input at which to begin matching
\r
2689 * @return length of input that matches, or -1 if match failure
\r
2691 private static int compareSimpleAffix(String affix, String input, int pos) {
\r
2693 for (int i=0; i<affix.length(); ) {
\r
2694 int c = UTF16.charAt(affix, i);
\r
2695 int len = UTF16.getCharCount(c);
\r
2696 if (UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2697 // We may have a pattern like: \u200F \u0020
\r
2698 // and input text like: \u200F \u0020
\r
2699 // Note that U+200F and U+0020 are RuleWhiteSpace but only
\r
2700 // U+0020 is UWhiteSpace. So we have to first do a direct
\r
2701 // match of the run of RULE whitespace in the pattern,
\r
2702 // then match any extra characters.
\r
2703 boolean literalMatch = false;
\r
2704 while (pos < input.length() &&
\r
2705 UTF16.charAt(input, pos) == c) {
\r
2706 literalMatch = true;
\r
2709 if (i == affix.length()) {
\r
2712 c = UTF16.charAt(affix, i);
\r
2713 len = UTF16.getCharCount(c);
\r
2714 if (!UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2719 // Advance over run in affix
\r
2720 i = skipRuleWhiteSpace(affix, i);
\r
2722 // Advance over run in input text
\r
2723 // Must see at least one white space char in input,
\r
2724 // unless we've already matched some characters literally.
\r
2726 pos = skipUWhiteSpace(input, pos);
\r
2727 if (pos == s && !literalMatch) {
\r
2730 // If we skip UWhiteSpace in the input text, we need to skip it in the pattern.
\r
2731 // Otherwise, the previous lines may have skipped over text (such as U+00A0) that
\r
2732 // is also in the affix.
\r
2733 i = skipUWhiteSpace(affix, i);
\r
2735 if (pos < input.length() &&
\r
2736 UTF16.charAt(input, pos) == c) {
\r
2744 return pos - start;
\r
2748 * Skip over a run of zero or more isRuleWhiteSpace() characters at
\r
2751 private static int skipRuleWhiteSpace(String text, int pos) {
\r
2752 while (pos < text.length()) {
\r
2753 int c = UTF16.charAt(text, pos);
\r
2754 if (!UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2757 pos += UTF16.getCharCount(c);
\r
2763 * Skip over a run of zero or more isUWhiteSpace() characters at pos
\r
2766 private static int skipUWhiteSpace(String text, int pos) {
\r
2767 while (pos < text.length()) {
\r
2768 int c = UTF16.charAt(text, pos);
\r
2769 if (!UCharacter.isUWhiteSpace(c)) {
\r
2772 pos += UTF16.getCharCount(c);
\r
2778 * Return the length matched by the given affix, or -1 if none.
\r
2779 * @param affixPat pattern string
\r
2780 * @param text input text
\r
2781 * @param pos offset into input at which to begin matching
\r
2782 * @param type parse against currency type, LONG_NAME only or not.
\r
2783 * @param currency return value for parsed currency, for generic
\r
2784 * currency parsing mode, or null for normal parsing. In generic
\r
2785 * currency parsing mode, any currency is parsed, not just the
\r
2786 * currency that this formatter is set to.
\r
2787 * @return position after the matched text, or -1 if match failure
\r
2789 private int compareComplexAffix(String affixPat, String text, int pos,
\r
2790 int type, Currency[] currency) {
\r
2793 i < affixPat.length() && pos >= 0; ) {
\r
2794 char c = affixPat.charAt(i++);
\r
2797 int j = affixPat.indexOf(QUOTE, i);
\r
2799 pos = match(text, pos, QUOTE);
\r
2802 } else if (j > i) {
\r
2803 pos = match(text, pos, affixPat.substring(i, j));
\r
2805 if (i<affixPat.length() &&
\r
2806 affixPat.charAt(i)==QUOTE) {
\r
2807 pos = match(text, pos, QUOTE);
\r
2814 // Unterminated quote; should be caught by apply
\r
2816 throw new RuntimeException();
\r
2823 case CURRENCY_SIGN:
\r
2824 // since the currency names in choice format is saved
\r
2825 // the same way as other currency names,
\r
2826 // do not need to do currency choice parsing here.
\r
2827 // the general currency parsing parse against all names,
\r
2828 // including names in choice format.
\r
2829 //assert(currency != null ||
\r
2830 // (getCurrency() != null && currencyChoice != null));
\r
2831 boolean intl = i<affixPat.length() &&
\r
2832 affixPat.charAt(i) == CURRENCY_SIGN;
\r
2836 boolean plural = i<affixPat.length() &&
\r
2837 affixPat.charAt(i) == CURRENCY_SIGN;
\r
2842 // Parse generic currency -- anything for which we
\r
2843 // have a display name, or any 3-letter ISO code.
\r
2844 // Try to parse display name for our locale; first
\r
2845 // determine our locale.
\r
2846 // TODO: use locale in CurrencyPluralInfo
\r
2847 ULocale uloc = getLocale(ULocale.VALID_LOCALE);
\r
2848 if (uloc == null) {
\r
2849 // applyPattern has been called; use the symbols
\r
2850 uloc = symbols.getLocale(ULocale.VALID_LOCALE);
\r
2852 // Delegate parse of display name => ISO code to Currency
\r
2853 ParsePosition ppos = new ParsePosition(pos);
\r
2854 // using Currency.parse to handle mixed style parsing.
\r
2855 String iso = Currency.parse(uloc, text, type, ppos);
\r
2857 // If parse succeeds, populate currency[0]
\r
2858 if (iso != null) {
\r
2859 if (currency != null) {
\r
2860 currency[0] = Currency.getInstance(iso);
\r
2862 pos = ppos.getIndex();
\r
2867 case PATTERN_PERCENT:
\r
2868 c = symbols.getPercent();
\r
2870 case PATTERN_PER_MILLE:
\r
2871 c = symbols.getPerMill();
\r
2873 case PATTERN_MINUS:
\r
2874 c = symbols.getMinusSign();
\r
2877 pos = match(text, pos, c);
\r
2878 if (UCharacterProperty.isRuleWhiteSpace(c)) {
\r
2879 i = skipRuleWhiteSpace(affixPat, i);
\r
2883 return pos - start;
\r
2887 * Match a single character at text[pos] and return the index of the
\r
2888 * next character upon success. Return -1 on failure. If
\r
2889 * isRuleWhiteSpace(ch) then match a run of white space in text.
\r
2891 static final int match(String text, int pos, int ch) {
\r
2892 if (pos >= text.length()) {
\r
2895 if (UCharacterProperty.isRuleWhiteSpace(ch)) {
\r
2896 // Advance over run of white space in input text
\r
2897 // Must see at least one white space char in input
\r
2899 pos = skipUWhiteSpace(text, pos);
\r
2905 return (pos >= 0 && UTF16.charAt(text, pos) == ch) ?
\r
2906 (pos + UTF16.getCharCount(ch)) : -1;
\r
2910 * Match a string at text[pos] and return the index of the next
\r
2911 * character upon success. Return -1 on failure. Match a run of
\r
2912 * white space in str with a run of white space in text.
\r
2914 static final int match(String text, int pos, String str) {
\r
2915 for (int i=0; i<str.length() && pos >= 0; ) {
\r
2916 int ch = UTF16.charAt(str, i);
\r
2917 i += UTF16.getCharCount(ch);
\r
2918 pos = match(text, pos, ch);
\r
2919 if (UCharacterProperty.isRuleWhiteSpace(ch)) {
\r
2920 i = skipRuleWhiteSpace(str, i);
\r
2927 * Returns a copy of the decimal format symbols used by this format.
\r
2928 * @return desired DecimalFormatSymbols
\r
2929 * @see DecimalFormatSymbols
\r
2932 public DecimalFormatSymbols getDecimalFormatSymbols() {
\r
2934 // don't allow multiple references
\r
2935 return (DecimalFormatSymbols) symbols.clone();
\r
2936 } catch (Exception foo) {
\r
2937 return null; // should never happen
\r
2943 * Sets the decimal format symbols used by this format. The
\r
2944 * format uses a copy of the provided symbols.
\r
2945 * @param newSymbols desired DecimalFormatSymbols
\r
2946 * @see DecimalFormatSymbols
\r
2949 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
\r
2950 symbols = (DecimalFormatSymbols) newSymbols.clone();
\r
2951 setCurrencyForSymbols();
\r
2952 expandAffixes(null);
\r
2956 * Update the currency object to match the symbols. This method
\r
2957 * is used only when the caller has passed in a symbols object
\r
2958 * that may not be the default object for its locale.
\r
2960 private void setCurrencyForSymbols() {
\r
2962 Update the affix strings according to symbols in order to keep
\r
2963 the affix strings up to date.
\r
2967 // With the introduction of the Currency object, the currency
\r
2968 // symbols in the DFS object are ignored. For backward
\r
2969 // compatibility, we check any explicitly set DFS object. If it
\r
2970 // is a default symbols object for its locale, we change the
\r
2971 // currency object to one for that locale. If it is custom,
\r
2972 // we set the currency to null.
\r
2973 DecimalFormatSymbols def =
\r
2974 new DecimalFormatSymbols(symbols.getLocale());
\r
2976 if (symbols.getCurrencySymbol().equals(
\r
2977 def.getCurrencySymbol()) &&
\r
2978 symbols.getInternationalCurrencySymbol().equals(
\r
2979 def.getInternationalCurrencySymbol())) {
\r
2980 setCurrency(Currency.getInstance(symbols.getLocale()));
\r
2982 setCurrency(null);
\r
2987 * Get the positive prefix.
\r
2988 * <P>Examples: +123, $123, sFr123
\r
2991 public String getPositivePrefix () {
\r
2992 return positivePrefix;
\r
2996 * Set the positive prefix.
\r
2997 * <P>Examples: +123, $123, sFr123
\r
3000 public void setPositivePrefix (String newValue) {
\r
3001 positivePrefix = newValue;
\r
3002 posPrefixPattern = null;
\r
3006 * Get the negative prefix.
\r
3007 * <P>Examples: -123, ($123) (with negative suffix), sFr-123
\r
3010 public String getNegativePrefix () {
\r
3011 return negativePrefix;
\r
3015 * Set the negative prefix.
\r
3016 * <P>Examples: -123, ($123) (with negative suffix), sFr-123
\r
3019 public void setNegativePrefix (String newValue) {
\r
3020 negativePrefix = newValue;
\r
3021 negPrefixPattern = null;
\r
3025 * Get the positive suffix.
\r
3026 * <P>Example: 123%
\r
3029 public String getPositiveSuffix () {
\r
3030 return positiveSuffix;
\r
3034 * Set the positive suffix.
\r
3035 * <P>Example: 123%
\r
3038 public void setPositiveSuffix (String newValue) {
\r
3039 positiveSuffix = newValue;
\r
3040 posSuffixPattern = null;
\r
3044 * Get the negative suffix.
\r
3045 * <P>Examples: -123%, ($123) (with positive suffixes)
\r
3048 public String getNegativeSuffix () {
\r
3049 return negativeSuffix;
\r
3053 * Set the positive suffix.
\r
3054 * <P>Examples: 123%
\r
3057 public void setNegativeSuffix (String newValue) {
\r
3058 negativeSuffix = newValue;
\r
3059 negSuffixPattern = null;
\r
3063 * Get the multiplier for use in percent, permill, etc.
\r
3064 * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
\r
3065 * (For Arabic, use arabic percent symbol).
\r
3066 * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
\r
3067 * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
\r
3070 public int getMultiplier () {
\r
3071 return multiplier;
\r
3075 * Set the multiplier for use in percent, permill, etc.
\r
3076 * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
\r
3077 * (For Arabic, use arabic percent symbol).
\r
3078 * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
\r
3079 * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
\r
3082 public void setMultiplier (int newValue) {
\r
3083 if (newValue == 0) {
\r
3084 throw new IllegalArgumentException("Bad multiplier: " + newValue);
\r
3086 multiplier = newValue;
\r
3091 * Get the rounding increment.
\r
3092 * @return A positive rounding increment, or <code>null</code> if rounding
\r
3093 * is not in effect.
\r
3094 * @see #setRoundingIncrement
\r
3095 * @see #getRoundingMode
\r
3096 * @see #setRoundingMode
\r
3099 //#if defined(FOUNDATION10) || defined(ECLIPSE_FRAGMENT)
\r
3100 //## public BigDecimal getRoundingIncrement() {
\r
3101 //## if (roundingIncrementICU == null) return null;
\r
3102 //## return new BigDecimal(roundingIncrementICU.toString());
\r
3105 public java.math.BigDecimal getRoundingIncrement() {
\r
3106 if (roundingIncrementICU == null) return null;
\r
3107 return roundingIncrementICU.toBigDecimal();
\r
3111 //#if defined(FOUNDATION10)
\r
3115 * Set the rounding increment. This method also controls whether
\r
3116 * rounding is enabled.
\r
3117 * @param newValue A positive rounding increment, or <code>null</code> or
\r
3118 * <code>BigDecimal(0.0)</code> to disable rounding.
\r
3119 * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
\r
3120 * @see #getRoundingIncrement
\r
3121 * @see #getRoundingMode
\r
3122 * @see #setRoundingMode
\r
3125 public void setRoundingIncrement(java.math.BigDecimal newValue) {
\r
3126 if (newValue == null) {
\r
3127 setRoundingIncrement((BigDecimal)null);
\r
3129 setRoundingIncrement(new BigDecimal(newValue));
\r
3136 * Set the rounding increment. This method also controls whether
\r
3137 * rounding is enabled.
\r
3138 * @param newValue A positive rounding increment, or <code>null</code> or
\r
3139 * <code>BigDecimal(0.0)</code> to disable rounding.
\r
3140 * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
\r
3141 * @see #getRoundingIncrement
\r
3142 * @see #getRoundingMode
\r
3143 * @see #setRoundingMode
\r
3146 public void setRoundingIncrement(BigDecimal newValue) {
\r
3147 int i = newValue == null
\r
3148 ? 0 : newValue.compareTo(BigDecimal.ZERO);
\r
3150 throw new IllegalArgumentException("Illegal rounding increment");
\r
3153 setInternalRoundingIncrement(null);
\r
3155 setInternalRoundingIncrement(newValue);
\r
3157 setRoundingDouble();
\r
3162 * Set the rounding increment. This method also controls whether
\r
3163 * rounding is enabled.
\r
3164 * @param newValue A positive rounding increment, or 0.0 to disable
\r
3166 * @exception IllegalArgumentException if <code>newValue</code> is < 0.0
\r
3167 * @see #getRoundingIncrement
\r
3168 * @see #getRoundingMode
\r
3169 * @see #setRoundingMode
\r
3172 public void setRoundingIncrement(double newValue) {
\r
3173 if (newValue < 0.0) {
\r
3174 throw new IllegalArgumentException("Illegal rounding increment");
\r
3176 roundingDouble = newValue;
\r
3177 roundingDoubleReciprocal = 0.0d;
\r
3178 if (newValue == 0.0d) {
\r
3179 setRoundingIncrement((BigDecimal)null);
\r
3181 roundingDouble = newValue;
\r
3182 if (roundingDouble < 1.0d) {
\r
3183 double rawRoundedReciprocal = 1.0d/roundingDouble;
\r
3184 setRoundingDoubleReciprocal(rawRoundedReciprocal);
\r
3186 setInternalRoundingIncrement(new BigDecimal(newValue));
\r
3191 private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {
\r
3192 roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);
\r
3193 if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {
\r
3194 roundingDoubleReciprocal = 0.0d;
\r
3198 static final double roundingIncrementEpsilon = 0.000000001;
\r
3201 * Get the rounding mode.
\r
3202 * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
\r
3203 * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
\r
3204 * @see #setRoundingIncrement
\r
3205 * @see #getRoundingIncrement
\r
3206 * @see #setRoundingMode
\r
3207 * @see java.math.BigDecimal
\r
3210 public int getRoundingMode() {
\r
3211 return roundingMode;
\r
3215 * Set the rounding mode. This has no effect unless the rounding
\r
3216 * increment is greater than zero.
\r
3217 * @param roundingMode A rounding mode, between
\r
3218 * <code>BigDecimal.ROUND_UP</code> and
\r
3219 * <code>BigDecimal.ROUND_UNNECESSARY</code>.
\r
3220 * @exception IllegalArgumentException if <code>roundingMode</code>
\r
3221 * is unrecognized.
\r
3222 * @see #setRoundingIncrement
\r
3223 * @see #getRoundingIncrement
\r
3224 * @see #getRoundingMode
\r
3225 * @see java.math.BigDecimal
\r
3228 public void setRoundingMode(int roundingMode) {
\r
3229 if (roundingMode < BigDecimal.ROUND_UP
\r
3230 || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
\r
3231 throw new IllegalArgumentException("Invalid rounding mode: "
\r
3235 this.roundingMode = roundingMode;
\r
3237 if (getRoundingIncrement() == null) {
\r
3238 setRoundingIncrement(Math.pow(10.0,(double)-getMaximumFractionDigits()));
\r
3244 * Get the width to which the output of <code>format()</code> is padded.
\r
3245 * The width is counted in 16-bit code units.
\r
3246 * @return the format width, or zero if no padding is in effect
\r
3247 * @see #setFormatWidth
\r
3248 * @see #getPadCharacter
\r
3249 * @see #setPadCharacter
\r
3250 * @see #getPadPosition
\r
3251 * @see #setPadPosition
\r
3254 public int getFormatWidth() {
\r
3255 return formatWidth;
\r
3260 * Set the width to which the output of <code>format()</code> is padded.
\r
3261 * The width is counted in 16-bit code units.
\r
3262 * This method also controls whether padding is enabled.
\r
3263 * @param width the width to which to pad the result of
\r
3264 * <code>format()</code>, or zero to disable padding
\r
3265 * @exception IllegalArgumentException if <code>width</code> is < 0
\r
3266 * @see #getFormatWidth
\r
3267 * @see #getPadCharacter
\r
3268 * @see #setPadCharacter
\r
3269 * @see #getPadPosition
\r
3270 * @see #setPadPosition
\r
3273 public void setFormatWidth(int width) {
\r
3275 throw new IllegalArgumentException("Illegal format width");
\r
3277 formatWidth = width;
\r
3282 * Get the character used to pad to the format width. The default is ' '.
\r
3283 * @return the pad character
\r
3284 * @see #setFormatWidth
\r
3285 * @see #getFormatWidth
\r
3286 * @see #setPadCharacter
\r
3287 * @see #getPadPosition
\r
3288 * @see #setPadPosition
\r
3291 public char getPadCharacter() {
\r
3297 * Set the character used to pad to the format width. If padding
\r
3298 * is not enabled, then this will take effect if padding is later
\r
3300 * @param padChar the pad character
\r
3301 * @see #setFormatWidth
\r
3302 * @see #getFormatWidth
\r
3303 * @see #getPadCharacter
\r
3304 * @see #getPadPosition
\r
3305 * @see #setPadPosition
\r
3308 public void setPadCharacter(char padChar) {
\r
3314 * Get the position at which padding will take place. This is the location
\r
3315 * at which padding will be inserted if the result of <code>format()</code>
\r
3316 * is shorter than the format width.
\r
3317 * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
\r
3318 * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
\r
3319 * <code>PAD_AFTER_SUFFIX</code>.
\r
3320 * @see #setFormatWidth
\r
3321 * @see #getFormatWidth
\r
3322 * @see #setPadCharacter
\r
3323 * @see #getPadCharacter
\r
3324 * @see #setPadPosition
\r
3325 * @see #PAD_BEFORE_PREFIX
\r
3326 * @see #PAD_AFTER_PREFIX
\r
3327 * @see #PAD_BEFORE_SUFFIX
\r
3328 * @see #PAD_AFTER_SUFFIX
\r
3331 public int getPadPosition() {
\r
3332 return padPosition;
\r
3337 * Set the position at which padding will take place. This is the location
\r
3338 * at which padding will be inserted if the result of <code>format()</code>
\r
3339 * is shorter than the format width. This has no effect unless padding is
\r
3341 * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,
\r
3342 * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or
\r
3343 * <code>PAD_AFTER_SUFFIX</code>.
\r
3344 * @exception IllegalArgumentException if the pad position in
\r
3346 * @see #setFormatWidth
\r
3347 * @see #getFormatWidth
\r
3348 * @see #setPadCharacter
\r
3349 * @see #getPadCharacter
\r
3350 * @see #getPadPosition
\r
3351 * @see #PAD_BEFORE_PREFIX
\r
3352 * @see #PAD_AFTER_PREFIX
\r
3353 * @see #PAD_BEFORE_SUFFIX
\r
3354 * @see #PAD_AFTER_SUFFIX
\r
3357 public void setPadPosition(int padPos) {
\r
3358 if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {
\r
3359 throw new IllegalArgumentException("Illegal pad position");
\r
3361 padPosition = padPos;
\r
3366 * Return whether or not scientific notation is used.
\r
3367 * @return true if this object formats and parses scientific notation
\r
3368 * @see #setScientificNotation
\r
3369 * @see #getMinimumExponentDigits
\r
3370 * @see #setMinimumExponentDigits
\r
3371 * @see #isExponentSignAlwaysShown
\r
3372 * @see #setExponentSignAlwaysShown
\r
3375 public boolean isScientificNotation() {
\r
3376 return useExponentialNotation;
\r
3381 * Set whether or not scientific notation is used. When scientific notation
\r
3382 * is used, the effective maximum number of integer digits is <= 8. If the
\r
3383 * maximum number of integer digits is set to more than 8, the effective
\r
3384 * maximum will be 1. This allows this call to generate a 'default' scientific
\r
3385 * number format without additional changes.
\r
3386 * @param useScientific true if this object formats and parses scientific
\r
3388 * @see #isScientificNotation
\r
3389 * @see #getMinimumExponentDigits
\r
3390 * @see #setMinimumExponentDigits
\r
3391 * @see #isExponentSignAlwaysShown
\r
3392 * @see #setExponentSignAlwaysShown
\r
3395 public void setScientificNotation(boolean useScientific) {
\r
3396 useExponentialNotation = useScientific;
\r
3401 * Return the minimum exponent digits that will be shown.
\r
3402 * @return the minimum exponent digits that will be shown
\r
3403 * @see #setScientificNotation
\r
3404 * @see #isScientificNotation
\r
3405 * @see #setMinimumExponentDigits
\r
3406 * @see #isExponentSignAlwaysShown
\r
3407 * @see #setExponentSignAlwaysShown
\r
3410 public byte getMinimumExponentDigits() {
\r
3411 return minExponentDigits;
\r
3416 * Set the minimum exponent digits that will be shown. This has no
\r
3417 * effect unless scientific notation is in use.
\r
3418 * @param minExpDig a value >= 1 indicating the fewest exponent digits
\r
3419 * that will be shown
\r
3420 * @exception IllegalArgumentException if <code>minExpDig</code> < 1
\r
3421 * @see #setScientificNotation
\r
3422 * @see #isScientificNotation
\r
3423 * @see #getMinimumExponentDigits
\r
3424 * @see #isExponentSignAlwaysShown
\r
3425 * @see #setExponentSignAlwaysShown
\r
3428 public void setMinimumExponentDigits(byte minExpDig) {
\r
3429 if (minExpDig < 1) {
\r
3430 throw new IllegalArgumentException("Exponent digits must be >= 1");
\r
3432 minExponentDigits = minExpDig;
\r
3437 * Return whether the exponent sign is always shown.
\r
3438 * @return true if the exponent is always prefixed with either the
\r
3439 * localized minus sign or the localized plus sign, false if only negative
\r
3440 * exponents are prefixed with the localized minus sign.
\r
3441 * @see #setScientificNotation
\r
3442 * @see #isScientificNotation
\r
3443 * @see #setMinimumExponentDigits
\r
3444 * @see #getMinimumExponentDigits
\r
3445 * @see #setExponentSignAlwaysShown
\r
3448 public boolean isExponentSignAlwaysShown() {
\r
3449 return exponentSignAlwaysShown;
\r
3454 * Set whether the exponent sign is always shown. This has no effect
\r
3455 * unless scientific notation is in use.
\r
3456 * @param expSignAlways true if the exponent is always prefixed with either
\r
3457 * the localized minus sign or the localized plus sign, false if only
\r
3458 * negative exponents are prefixed with the localized minus sign.
\r
3459 * @see #setScientificNotation
\r
3460 * @see #isScientificNotation
\r
3461 * @see #setMinimumExponentDigits
\r
3462 * @see #getMinimumExponentDigits
\r
3463 * @see #isExponentSignAlwaysShown
\r
3466 public void setExponentSignAlwaysShown(boolean expSignAlways) {
\r
3467 exponentSignAlwaysShown = expSignAlways;
\r
3471 * Return the grouping size. Grouping size is the number of digits between
\r
3472 * grouping separators in the integer portion of a number. For example,
\r
3473 * in the number "123,456.78", the grouping size is 3.
\r
3474 * @see #setGroupingSize
\r
3475 * @see NumberFormat#isGroupingUsed
\r
3476 * @see DecimalFormatSymbols#getGroupingSeparator
\r
3479 public int getGroupingSize () {
\r
3480 return groupingSize;
\r
3484 * Set the grouping size. Grouping size is the number of digits between
\r
3485 * grouping separators in the integer portion of a number. For example,
\r
3486 * in the number "123,456.78", the grouping size is 3.
\r
3487 * @see #getGroupingSize
\r
3488 * @see NumberFormat#setGroupingUsed
\r
3489 * @see DecimalFormatSymbols#setGroupingSeparator
\r
3492 public void setGroupingSize (int newValue) {
\r
3493 groupingSize = (byte)newValue;
\r
3498 * Return the secondary grouping size. In some locales one
\r
3499 * grouping interval is used for the least significant integer
\r
3500 * digits (the primary grouping size), and another is used for all
\r
3501 * others (the secondary grouping size). A formatter supporting a
\r
3502 * secondary grouping size will return a positive integer unequal
\r
3503 * to the primary grouping size returned by
\r
3504 * <code>getGroupingSize()</code>. For example, if the primary
\r
3505 * grouping size is 4, and the secondary grouping size is 2, then
\r
3506 * the number 123456789 formats as "1,23,45,6789", and the pattern
\r
3507 * appears as "#,##,###0".
\r
3508 * @return the secondary grouping size, or a value less than
\r
3509 * one if there is none
\r
3510 * @see #setSecondaryGroupingSize
\r
3511 * @see NumberFormat#isGroupingUsed
\r
3512 * @see DecimalFormatSymbols#getGroupingSeparator
\r
3515 public int getSecondaryGroupingSize () {
\r
3516 return groupingSize2;
\r
3521 * Set the secondary grouping size. If set to a value less than 1,
\r
3522 * then secondary grouping is turned off, and the primary grouping
\r
3523 * size is used for all intervals, not just the least significant.
\r
3524 * @see #getSecondaryGroupingSize
\r
3525 * @see NumberFormat#setGroupingUsed
\r
3526 * @see DecimalFormatSymbols#setGroupingSeparator
\r
3529 public void setSecondaryGroupingSize (int newValue) {
\r
3530 groupingSize2 = (byte)newValue;
\r
3535 * Returns the MathContext
\r
3536 * used by this format.
\r
3537 * @return desired MathContext
\r
3538 * @see #mathContext
\r
3539 * @see #getMathContext
\r
3541 * @provisional This API might change or be removed in a future release.
\r
3543 public MathContext getMathContextICU() {
\r
3544 return mathContext;
\r
3547 //#if defined(FOUNDATION10) || defined(J2SE13) || defined(J2SE14) || defined(ECLIPSE_FRAGMENT)
\r
3551 * Returns the MathContext
\r
3552 * used by this format.
\r
3553 * @return desired MathContext
\r
3554 * @see #mathContext
\r
3555 * @see #getMathContext
\r
3557 * @provisional This API might change or be removed in a future release.
\r
3559 public java.math.MathContext getMathContext()
\r
3563 // don't allow multiple references
\r
3564 return mathContext == null ?
\r
3566 new java.math.MathContext(mathContext.getDigits(),
\r
3567 java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));
\r
3569 catch (Exception foo)
\r
3571 return null; // should never happen
\r
3578 * Sets the MathContext used by this format.
\r
3579 * @param newValue desired MathContext
\r
3580 * @see #mathContext
\r
3581 * @see #getMathContext
\r
3583 * @provisional This API might change or be removed in a future release.
\r
3585 public void setMathContextICU(MathContext newValue) {
\r
3586 mathContext = newValue;
\r
3589 //#if defined(FOUNDATION10) || defined(J2SE13) || defined(J2SE14) || defined(ECLIPSE_FRAGMENT)
\r
3593 * Sets the MathContext used by this format.
\r
3594 * @param newValue desired MathContext
\r
3595 * @see #mathContext
\r
3596 * @see #getMathContext
\r
3598 * @provisional This API might change or be removed in a future release.
\r
3600 public void setMathContext(java.math.MathContext newValue)
\r
3602 mathContext = new MathContext(newValue.getPrecision(),
\r
3603 MathContext.SCIENTIFIC,
\r
3605 (newValue.getRoundingMode()).ordinal()
\r
3611 * Allows you to get the behavior of the decimal separator with integers.
\r
3612 * (The decimal separator will always appear with decimals.)
\r
3613 * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
\r
3616 public boolean isDecimalSeparatorAlwaysShown() {
\r
3617 return decimalSeparatorAlwaysShown;
\r
3621 * Allows you to set the behavior of the decimal separator with integers.
\r
3622 * (The decimal separator will always appear with decimals.)
\r
3624 * <p>This only affects formatting, and only where
\r
3625 * there might be no digits after the decimal point, e.g.,
\r
3626 * if true, 3456.00 -> "3,456."
\r
3627 * if false, 3456.00 -> "3456"
\r
3628 * This is independent of parsing. If you want parsing to stop at the decimal
\r
3629 * point, use setParseIntegerOnly.
\r
3631 * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
\r
3634 public void setDecimalSeparatorAlwaysShown(boolean newValue) {
\r
3635 decimalSeparatorAlwaysShown = newValue;
\r
3639 * Returns a copy of the CurrencyPluralInfo
\r
3640 * used by this format.
\r
3641 * It might return null if the decimal format is not a plural type
\r
3642 * currency decimal format.
\r
3643 * Plural type currency decimal format means either
\r
3644 * the pattern in the decimal format contains 3 currency signs,
\r
3645 * or the decimal format is initialized with PLURALCURRENCYSTYLE.
\r
3646 * @return desired CurrencyPluralInfo
\r
3647 * @see CurrencyPluralInfo
\r
3649 * @provisional This API might change or be removed in a future release.
\r
3651 public CurrencyPluralInfo getCurrencyPluralInfo() {
\r
3653 // don't allow multiple references
\r
3654 return currencyPluralInfo == null ?
\r
3656 (CurrencyPluralInfo) currencyPluralInfo.clone();
\r
3657 } catch (Exception foo) {
\r
3658 return null; // should never happen
\r
3664 * Sets the CurrencyPluralInfo used by this format. The
\r
3665 * format uses a copy of the provided information.
\r
3666 * @param newInfo desired CurrencyPluralInfo
\r
3667 * @see CurrencyPluralInfo
\r
3669 * @provisional This API might change or be removed in a future release.
\r
3671 public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
\r
3672 currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();
\r
3673 isReadyForParsing = false;
\r
3677 * Standard override; no change in semantics.
\r
3680 public Object clone() {
\r
3682 DecimalFormat other = (DecimalFormat) super.clone();
\r
3683 other.symbols = (DecimalFormatSymbols) symbols.clone();
\r
3684 other.digitList = new DigitList(); // fix for JB#5358
\r
3685 if (currencyPluralInfo != null) {
\r
3686 other.currencyPluralInfo = (CurrencyPluralInfo)currencyPluralInfo.clone();
\r
3689 * TODO: We need to figure out whether we share a single copy
\r
3690 * of DigitList by multiple cloned copies. format/subformat
\r
3691 * are designed to use a single instance, but parse/subparse
\r
3692 * implementation is not.
\r
3695 } catch (Exception e) {
\r
3696 throw new IllegalStateException();
\r
3701 * Overrides equals
\r
3704 public boolean equals(Object obj)
\r
3706 if (obj == null) return false;
\r
3707 if (!super.equals(obj)) return false; // super does class check
\r
3709 DecimalFormat other = (DecimalFormat) obj;
\r
3710 /* Add the comparison of the four new added fields ,they are
\r
3711 * posPrefixPattern, posSuffixPattern, negPrefixPattern, negSuffixPattern.
\r
3714 // following are added to accomodate changes for currency plural format.
\r
3715 return currencySignCount == other.currencySignCount
\r
3716 && (style != NumberFormat.PLURALCURRENCYSTYLE ||
\r
3717 equals(posPrefixPattern, other.posPrefixPattern)
\r
3718 && equals(posSuffixPattern, other.posSuffixPattern)
\r
3719 && equals(negPrefixPattern, other.negPrefixPattern)
\r
3720 && equals(negSuffixPattern, other.negSuffixPattern))
\r
3721 && multiplier == other.multiplier
\r
3722 && groupingSize == other.groupingSize
\r
3723 && groupingSize2 == other.groupingSize2
\r
3724 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
\r
3725 && useExponentialNotation == other.useExponentialNotation
\r
3726 && (!useExponentialNotation ||
\r
3727 minExponentDigits == other.minExponentDigits)
\r
3728 && useSignificantDigits == other.useSignificantDigits
\r
3729 && (!useSignificantDigits ||
\r
3730 minSignificantDigits == other.minSignificantDigits &&
\r
3731 maxSignificantDigits == other.maxSignificantDigits)
\r
3732 && symbols.equals(other.symbols)
\r
3733 && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);
\r
3736 //method to unquote the strings and compare
\r
3737 private boolean equals(String pat1, String pat2){
\r
3738 if (pat1 == null || pat2 == null) {
\r
3739 return (pat1 == null && pat2 == null);
\r
3742 if(pat1.equals(pat2)){
\r
3745 return unquote(pat1).equals(unquote(pat2));
\r
3747 private String unquote(String pat){
\r
3748 StringBuffer buf = new StringBuffer(pat.length());
\r
3750 while(i<pat.length()){
\r
3751 char ch = pat.charAt(i++);
\r
3756 return buf.toString();
\r
3758 // protected void handleToString(StringBuffer buf) {
\r
3759 // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");
\r
3760 // buf.append("positivePrefix: '" + positivePrefix + "'\n");
\r
3761 // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");
\r
3762 // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");
\r
3763 // buf.append("negPrefixPattern: '" + com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");
\r
3764 // buf.append("negativePrefix: '" + com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");
\r
3765 // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");
\r
3766 // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");
\r
3767 // buf.append("multiplier: '" + multiplier + "'\n");
\r
3768 // buf.append("groupingSize: '" + groupingSize + "'\n");
\r
3769 // buf.append("groupingSize2: '" + groupingSize2 + "'\n");
\r
3770 // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");
\r
3771 // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");
\r
3772 // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");
\r
3773 // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");
\r
3774 // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");
\r
3775 // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");
\r
3776 // buf.append("symbols: '" + symbols + "'");
\r
3780 * Overrides hashCode
\r
3783 public int hashCode() {
\r
3784 return super.hashCode() * 37 + positivePrefix.hashCode();
\r
3785 // just enough fields for a reasonable distribution
\r
3789 * Synthesizes a pattern string that represents the current state
\r
3790 * of this Format object.
\r
3791 * @see #applyPattern
\r
3794 public String toPattern() {
\r
3795 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
3796 // the prefix or suffix pattern might not be defined yet,
\r
3797 // so they can not be synthesized,
\r
3798 // instead, get them directly.
\r
3799 // but it might not be the actual pattern used in formatting.
\r
3800 // the actual pattern used in formatting depends on the
\r
3801 // formatted number's plural count.
\r
3802 return formatPattern;
\r
3804 return toPattern( false );
\r
3808 * Synthesizes a localized pattern string that represents the current
\r
3809 * state of this Format object.
\r
3810 * @see #applyPattern
\r
3813 public String toLocalizedPattern() {
\r
3814 if (style == NumberFormat.PLURALCURRENCYSTYLE) {
\r
3815 return formatPattern;
\r
3817 return toPattern( true );
\r
3821 * Expand the affix pattern strings into the expanded affix strings. If any
\r
3822 * affix pattern string is null, do not expand it. This method should be
\r
3823 * called any time the symbols or the affix patterns change in order to keep
\r
3824 * the expanded affix strings up to date.
\r
3825 * This method also will be called before formatting if format currency
\r
3826 * plural names, since the plural name is not a static one, it is
\r
3827 * based on the currency plural count, the affix will be known only
\r
3828 * after the currency plural count is know.
\r
3829 * In which case, the parameter
\r
3830 * 'pluralCount' will be a non-null currency plural count.
\r
3831 * In all other cases, the 'pluralCount' is null, which means
\r
3832 * it is not needed.
\r
3834 //Bug 4212072 [Richard/GCL]
\r
3835 private void expandAffixes(String pluralCount) {
\r
3836 // expandAffix() will set currencyChoice to a non-null value if
\r
3837 // appropriate AND if it is null.
\r
3838 currencyChoice = null;
\r
3840 // Reuse one StringBuffer for better performance
\r
3841 StringBuffer buffer = new StringBuffer();
\r
3842 if (posPrefixPattern != null) {
\r
3843 expandAffix(posPrefixPattern, pluralCount, buffer, false);
\r
3844 positivePrefix = buffer.toString();
\r
3846 if (posSuffixPattern != null) {
\r
3847 expandAffix(posSuffixPattern, pluralCount, buffer, false);
\r
3848 positiveSuffix = buffer.toString();
\r
3850 if (negPrefixPattern != null) {
\r
3851 expandAffix(negPrefixPattern, pluralCount, buffer, false);
\r
3852 negativePrefix = buffer.toString();
\r
3854 if (negSuffixPattern != null) {
\r
3855 expandAffix(negSuffixPattern, pluralCount, buffer, false);
\r
3856 negativeSuffix = buffer.toString();
\r
3861 * Expand an affix pattern into an affix string. All characters in
\r
3862 * the pattern are literal unless bracketed by QUOTEs. The
\r
3863 * following characters outside QUOTE are recognized:
\r
3864 * PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and
\r
3865 * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as
\r
3866 * an international currency sign. If CURRENCY_SIGN is tripled,
\r
3867 * it is interpreted as currency plural long names, such as "US Dollars".
\r
3868 * Any other character outside
\r
3869 * QUOTE represents itself. Quoted text must be well-formed.
\r
3871 * This method is used in two distinct ways. First, it is used to expand
\r
3872 * the stored affix patterns into actual affixes. For this usage, doFormat
\r
3873 * must be false. Second, it is used to expand the stored affix patterns
\r
3874 * given a specific number (doFormat == true), for those rare cases in
\r
3875 * which a currency format references a ChoiceFormat (e.g., en_IN display
\r
3876 * name for INR). The number itself is taken from digitList.
\r
3878 * When used in the first way, this method has a side effect: It sets
\r
3879 * currencyChoice to a ChoiceFormat object, if the currency's display name
\r
3880 * in this locale is a ChoiceFormat pattern (very rare). It only does this
\r
3881 * if currencyChoice is null to start with.
\r
3883 * @param pattern the non-null, possibly empty pattern
\r
3884 * @param pluralCount the plural count. It is only used for currency
\r
3885 * plural format. In which case, it is the plural
\r
3886 * count of the currency amount. For example,
\r
3887 * in en_US, it is the singular "one", or the plural
\r
3888 * "other". For all other cases, it is null, and
\r
3889 * is not being used.
\r
3890 * @param buffer a scratch StringBuffer; its contents will be lost
\r
3891 * @param doFormat if false, then the pattern will be expanded, and if a
\r
3892 * currency symbol is encountered that expands to a ChoiceFormat, the
\r
3893 * currencyChoice member variable will be initialized if it is null. If
\r
3894 * doFormat is true, then it is assumed that the currencyChoice has been
\r
3895 * created, and it will be used to format the value in digitList.
\r
3896 * @return the expanded equivalent of pattern
\r
3898 //Bug 4212072 [Richard/GCL]
\r
3899 private void expandAffix(String pattern,
\r
3900 String pluralCount,
\r
3901 StringBuffer buffer,
\r
3902 boolean doFormat) {
\r
3903 buffer.setLength(0);
\r
3904 for (int i=0; i<pattern.length(); ) {
\r
3905 char c = pattern.charAt(i++);
\r
3908 int j = pattern.indexOf(QUOTE, i);
\r
3910 buffer.append(QUOTE);
\r
3913 } else if (j > i) {
\r
3914 buffer.append(pattern.substring(i, j));
\r
3916 if (i<pattern.length() &&
\r
3917 pattern.charAt(i)==QUOTE) {
\r
3918 buffer.append(QUOTE);
\r
3925 // Unterminated quote; should be caught by apply
\r
3927 throw new RuntimeException();
\r
3934 case CURRENCY_SIGN:
\r
3935 // As of ICU 2.2 we use the currency object, and
\r
3936 // ignore the currency symbols in the DFS, unless
\r
3937 // we have a null currency object. This occurs if
\r
3938 // resurrecting a pre-2.2 object or if the user
\r
3939 // sets a custom DFS.
\r
3940 boolean intl = i<pattern.length() &&
\r
3941 pattern.charAt(i) == CURRENCY_SIGN;
\r
3942 boolean plural = false;
\r
3945 if (i<pattern.length() &&
\r
3946 pattern.charAt(i) == CURRENCY_SIGN) {
\r
3953 Currency currency = getCurrency();
\r
3954 if (currency != null) {
\r
3955 // plural name is only needed when pluralCount != null,
\r
3956 // which means when formatting currency plural names.
\r
3957 // For other cases, pluralCount == null,
\r
3958 // and plural names are not needed.
\r
3959 if (plural && pluralCount != null) {
\r
3960 boolean isChoiceFormat[] = new boolean[1];
\r
3961 s = currency.getName(symbols.getULocale(),
\r
3962 Currency.PLURAL_LONG_NAME,
\r
3967 boolean isChoiceFormat[] = new boolean[1];
\r
3968 s = currency.getName(symbols.getULocale(),
\r
3969 Currency.SYMBOL_NAME,
\r
3971 if (isChoiceFormat[0]) {
\r
3972 // Two modes here: If doFormat is false, we set up
\r
3973 // currencyChoice. If doFormat is true, we use the
\r
3974 // previously created currencyChoice to format the
\r
3975 // value in digitList.
\r
3977 // If the currency is handled by a ChoiceFormat,
\r
3978 // then we're not going to use the expanded
\r
3979 // patterns. Instantiate the ChoiceFormat and
\r
3981 if (currencyChoice == null) {
\r
3982 currencyChoice = new ChoiceFormat(s);
\r
3984 // We could almost return null or "" here, since the
\r
3985 // expanded affixes are almost not used at all
\r
3986 // in this situation. However, one method --
\r
3987 // toPattern() -- still does use the expanded
\r
3988 // affixes, in order to set up a padding
\r
3989 // pattern. We use the CURRENCY_SIGN as a
\r
3991 s = String.valueOf(CURRENCY_SIGN);
\r
3993 FieldPosition pos = new FieldPosition(0); // ignored
\r
3994 currencyChoice.format(digitList.getDouble(), buffer, pos);
\r
3999 s = currency.getCurrencyCode();
\r
4002 s = intl ? symbols.getInternationalCurrencySymbol()
\r
4003 : symbols.getCurrencySymbol();
\r
4007 case PATTERN_PERCENT:
\r
4008 c = symbols.getPercent();
\r
4010 case PATTERN_PER_MILLE:
\r
4011 c = symbols.getPerMill();
\r
4013 case PATTERN_MINUS:
\r
4014 c = symbols.getMinusSign();
\r
4022 * Append an affix to the given StringBuffer.
\r
4023 * @param buf buffer to append to
\r
4024 * @param isNegative
\r
4027 private int appendAffix(StringBuffer buf, boolean isNegative,
\r
4028 boolean isPrefix, boolean parseAttr) {
\r
4029 if (currencyChoice != null) {
\r
4030 String affixPat = null;
\r
4032 affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
\r
4034 affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
\r
4036 StringBuffer affixBuf = new StringBuffer();
\r
4037 expandAffix(affixPat, null, affixBuf, true);
\r
4038 buf.append(affixBuf.toString());
\r
4039 return affixBuf.length();
\r
4042 String affix = null;
\r
4044 affix = isNegative ? negativePrefix : positivePrefix;
\r
4046 affix = isNegative ? negativeSuffix : positiveSuffix;
\r
4048 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
4050 // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
\r
4052 int offset = affix.indexOf(symbols.getCurrencySymbol());
\r
4053 if (-1 == offset) {
\r
4054 offset = affix.indexOf(symbols.getPercent());
\r
4055 if(-1 == offset) {
\r
4059 formatAffix2Attribute(affix, buf.length() + offset, buf.length()
\r
4060 + affix.length());
\r
4063 buf.append(affix);
\r
4064 return affix.length();
\r
4067 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
4070 * [Spark/CDL] This is a newly added method, used to add attributes for
\r
4071 * prefix and suffix.
\r
4073 private void formatAffix2Attribute(String affix, int begin, int end) {
\r
4074 // [Spark/CDL] It is the invoker's responsibility to ensure that, before
\r
4075 // the invocation of
\r
4076 // this method, attributes is not null.
\r
4077 // if( attributes == null ) return;
\r
4078 if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
\r
4079 addAttribute(Field.CURRENCY, begin, end);
\r
4080 } else if (affix.indexOf(symbols.getMinusSign()) > -1) {
\r
4081 addAttribute(Field.SIGN, begin, end);
\r
4082 } else if (affix.indexOf(symbols.getPercent()) > -1) {
\r
4083 addAttribute(Field.PERCENT, begin, end);
\r
4084 } else if (affix.indexOf(symbols.getPerMill()) > -1) {
\r
4085 addAttribute(Field.PERMILLE, begin, end);
\r
4090 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
4093 * [Spark/CDL] Use this method to add attribute.
\r
4095 private void addAttribute(Field field, int begin, int end) {
\r
4096 FieldPosition pos = new FieldPosition(field);
\r
4097 pos.setBeginIndex(begin);
\r
4098 pos.setEndIndex(end);
\r
4099 attributes.add(pos);
\r
4103 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
4106 * Format the object to an attributed string, and return the corresponding iterator
\r
4107 * Overrides superclass method.
\r
4111 public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
\r
4112 if (!(obj instanceof Number))
\r
4113 throw new IllegalArgumentException();
\r
4114 Number number = (Number) obj;
\r
4115 StringBuffer text = null;
\r
4116 attributes.clear();
\r
4117 if (obj instanceof BigInteger) {
\r
4118 text = format((BigInteger) number, new StringBuffer(),
\r
4119 new FieldPosition(0), true);
\r
4120 } else if (obj instanceof java.math.BigDecimal) {
\r
4121 text = format((java.math.BigDecimal) number, new StringBuffer(),
\r
4122 new FieldPosition(0), true);
\r
4123 } else if (obj instanceof Double) {
\r
4124 text = format(number.doubleValue(), new StringBuffer(),
\r
4125 new FieldPosition(0), true);
\r
4126 } else if (obj instanceof Integer || obj instanceof Long) {
\r
4127 text = format(number.longValue(), new StringBuffer(),
\r
4128 new FieldPosition(0), true);
\r
4131 AttributedString as = new AttributedString(text.toString());
\r
4133 // add NumberFormat field attributes to the AttributedString
\r
4134 for (int i = 0; i < attributes.size(); i++) {
\r
4135 FieldPosition pos = (FieldPosition) attributes.get(i);
\r
4136 Format.Field attribute = pos.getFieldAttribute();
\r
4137 as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
\r
4141 // return the CharacterIterator from AttributedString
\r
4142 return as.getIterator();
\r
4146 * Append an affix pattern to the given StringBuffer. Localize unquoted
\r
4149 private void appendAffixPattern(StringBuffer buffer,
\r
4150 boolean isNegative, boolean isPrefix,
\r
4151 boolean localized) {
\r
4152 String affixPat = null;
\r
4154 affixPat = isNegative ? negPrefixPattern : posPrefixPattern;
\r
4156 affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
\r
4159 // When there is a null affix pattern, we use the affix itself.
\r
4160 if (affixPat == null) {
\r
4161 String affix = null;
\r
4163 affix = isNegative ? negativePrefix : positivePrefix;
\r
4165 affix = isNegative ? negativeSuffix : positiveSuffix;
\r
4167 // Do this crudely for now: Wrap everything in quotes.
\r
4168 buffer.append(QUOTE);
\r
4169 for (int i=0; i<affix.length(); ++i) {
\r
4170 char ch = affix.charAt(i);
\r
4171 if (ch == QUOTE) {
\r
4172 buffer.append(ch);
\r
4174 buffer.append(ch);
\r
4176 buffer.append(QUOTE);
\r
4181 buffer.append(affixPat);
\r
4184 for (i=0; i<affixPat.length(); ++i) {
\r
4185 char ch = affixPat.charAt(i);
\r
4188 j = affixPat.indexOf(QUOTE, i+1);
\r
4190 throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);
\r
4192 buffer.append(affixPat.substring(i, j+1));
\r
4195 case PATTERN_PER_MILLE:
\r
4196 ch = symbols.getPerMill();
\r
4198 case PATTERN_PERCENT:
\r
4199 ch = symbols.getPercent();
\r
4201 case PATTERN_MINUS:
\r
4202 ch = symbols.getMinusSign();
\r
4205 //check if char is same as any other symbol
\r
4206 if(ch==symbols.getDecimalSeparator() ||
\r
4207 ch==symbols.getGroupingSeparator() ){
\r
4208 buffer.append(QUOTE);
\r
4209 buffer.append(ch);
\r
4210 buffer.append(QUOTE);
\r
4212 buffer.append(ch);
\r
4219 * <strong><font face=helvetica color=red>CHANGED</font></strong>
\r
4220 * Does the real work of generating a pattern.
\r
4222 private String toPattern(boolean localized) {
\r
4223 StringBuffer result = new StringBuffer();
\r
4224 char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;
\r
4225 char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;
\r
4226 char sigDigit = 0;
\r
4227 boolean useSigDig = areSignificantDigitsUsed();
\r
4229 sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;
\r
4231 char group = localized ? symbols.getGroupingSeparator()
\r
4232 : PATTERN_GROUPING_SEPARATOR;
\r
4234 int roundingDecimalPos = 0; // Pos of decimal in roundingDigits
\r
4235 String roundingDigits = null;
\r
4236 int padPos = (formatWidth > 0) ? padPosition : -1;
\r
4237 String padSpec = (formatWidth > 0)
\r
4238 ? new StringBuffer(2).
\r
4239 append(localized ? symbols.getPadEscape() : PATTERN_PAD_ESCAPE).
\r
4240 append(pad).toString()
\r
4242 if (roundingIncrementICU != null) {
\r
4243 i = roundingIncrementICU.scale();
\r
4244 roundingDigits = roundingIncrementICU.movePointRight(i).toString();
\r
4245 roundingDecimalPos = roundingDigits.length() - i;
\r
4247 for (int part=0; part<2; ++part) {
\r
4248 // variable not used int partStart = result.length();
\r
4249 if (padPos == PAD_BEFORE_PREFIX) {
\r
4250 result.append(padSpec);
\r
4252 /* Use original symbols read from resources in pattern
\r
4253 * eg. use "\u00A4" instead of "$" in Locale.US [Richard/GCL]
\r
4255 appendAffixPattern(result, part!=0, true, localized);
\r
4256 if (padPos == PAD_AFTER_PREFIX) {
\r
4257 result.append(padSpec);
\r
4259 int sub0Start = result.length();
\r
4260 int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;
\r
4261 if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {
\r
4262 g += groupingSize2;
\r
4264 int maxDig = 0, minDig = 0, maxSigDig = 0;
\r
4266 minDig = getMinimumSignificantDigits();
\r
4267 maxDig = maxSigDig = getMaximumSignificantDigits();
\r
4269 minDig = getMinimumIntegerDigits();
\r
4270 maxDig = getMaximumIntegerDigits();
\r
4272 if (useExponentialNotation) {
\r
4273 if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {
\r
4276 } else if (useSigDig) {
\r
4277 maxDig = Math.max(maxDig, g+1);
\r
4279 maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()),
\r
4280 roundingDecimalPos) + 1;
\r
4282 for (i = maxDig; i > 0; --i) {
\r
4283 if (!useExponentialNotation && i<maxDig &&
\r
4284 isGroupingPosition(i)) {
\r
4285 result.append(group);
\r
4288 // #@,@### (maxSigDig == 5, minSigDig == 2)
\r
4289 // 65 4321 (1-based pos, count from the right)
\r
4290 // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
\r
4291 // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
\r
4292 result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);
\r
4294 if (roundingDigits != null) {
\r
4295 int pos = roundingDecimalPos - i;
\r
4296 if (pos >= 0 && pos < roundingDigits.length()) {
\r
4297 result.append((char) (roundingDigits.charAt(pos) - '0' + zero));
\r
4301 result.append(i<=minDig ? zero : digit);
\r
4305 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {
\r
4306 result.append(localized ? symbols.getDecimalSeparator() :
\r
4307 PATTERN_DECIMAL_SEPARATOR);
\r
4309 int pos = roundingDecimalPos;
\r
4310 for (i = 0; i < getMaximumFractionDigits(); ++i) {
\r
4311 if (roundingDigits != null &&
\r
4312 pos < roundingDigits.length()) {
\r
4313 result.append(pos < 0 ? zero :
\r
4314 (char) (roundingDigits.charAt(pos) - '0' + zero));
\r
4318 result.append(i<getMinimumFractionDigits() ? zero : digit);
\r
4321 if (useExponentialNotation) {
\r
4323 result.append(symbols.getExponentSeparator() );
\r
4325 result.append(PATTERN_EXPONENT);
\r
4327 if (exponentSignAlwaysShown) {
\r
4328 result.append(localized ? symbols.getPlusSign() :
\r
4329 PATTERN_PLUS_SIGN);
\r
4331 for (i=0; i<minExponentDigits; ++i) {
\r
4332 result.append(zero);
\r
4335 if (padSpec != null && !useExponentialNotation) {
\r
4336 int add = formatWidth - result.length() + sub0Start
\r
4338 ? positivePrefix.length() + positiveSuffix.length()
\r
4339 : negativePrefix.length() + negativeSuffix.length());
\r
4341 result.insert(sub0Start, digit);
\r
4344 // Only add a grouping separator if we have at least
\r
4345 // 2 additional characters to be added, so we don't
\r
4346 // end up with ",###".
\r
4347 if (add>1 && isGroupingPosition(maxDig)) {
\r
4348 result.insert(sub0Start, group);
\r
4353 if (padPos == PAD_BEFORE_SUFFIX) {
\r
4354 result.append(padSpec);
\r
4356 /* Use original symbols read from resources in pattern
\r
4357 * eg. use "\u00A4" instead of "$" in Locale.US [Richard/GCL]
\r
4359 appendAffixPattern(result, part!=0, false, localized);
\r
4360 if (padPos == PAD_AFTER_SUFFIX) {
\r
4361 result.append(padSpec);
\r
4364 if (negativeSuffix.equals(positiveSuffix) &&
\r
4365 negativePrefix.equals( PATTERN_MINUS + positivePrefix)) {
\r
4368 result.append(localized ? symbols.getPatternSeparator() :
\r
4369 PATTERN_SEPARATOR);
\r
4373 return result.toString();
\r
4377 * Apply the given pattern to this Format object. A pattern is a
\r
4378 * short-hand specification for the various formatting properties.
\r
4379 * These properties can also be changed individually through the
\r
4380 * various setter methods.
\r
4382 * There is no limit to integer digits are set
\r
4383 * by this routine, since that is the typical end-user desire;
\r
4384 * use setMaximumInteger if you want to set a real value.
\r
4385 * For negative numbers, use a second pattern, separated by a semicolon
\r
4386 * <P>Example "#,#00.0#" -> 1,234.56
\r
4387 * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
\r
4388 * a maximum of 2 fraction digits.
\r
4389 * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.
\r
4390 * <p>In negative patterns, the minimum and maximum counts are ignored;
\r
4391 * these are presumed to be set in the positive pattern.
\r
4394 public void applyPattern( String pattern ) {
\r
4395 applyPattern( pattern, false );
\r
4399 * Apply the given pattern to this Format object. The pattern
\r
4400 * is assumed to be in a localized notation. A pattern is a
\r
4401 * short-hand specification for the various formatting properties.
\r
4402 * These properties can also be changed individually through the
\r
4403 * various setter methods.
\r
4405 * There is no limit to integer digits are set
\r
4406 * by this routine, since that is the typical end-user desire;
\r
4407 * use setMaximumInteger if you want to set a real value.
\r
4408 * For negative numbers, use a second pattern, separated by a semicolon
\r
4409 * <P>Example "#,#00.0#" -> 1,234.56
\r
4410 * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
\r
4411 * a maximum of 2 fraction digits.
\r
4412 * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
\r
4413 * <p>In negative patterns, the minimum and maximum counts are ignored;
\r
4414 * these are presumed to be set in the positive pattern.
\r
4417 public void applyLocalizedPattern( String pattern ) {
\r
4418 applyPattern( pattern, true );
\r
4423 * <strong><font face=helvetica color=red>CHANGED</font></strong>
\r
4424 * Does the real work of applying a pattern.
\r
4426 private void applyPattern(String pattern, boolean localized) {
\r
4427 applyPatternWithoutExpandAffix(pattern, localized);
\r
4428 expandAffixAdjustWidth(null);
\r
4431 private void expandAffixAdjustWidth(String pluralCount) {
\r
4433 Update the affix strings according to symbols in order to keep
\r
4434 the affix strings up to date.
\r
4437 expandAffixes(pluralCount);
\r
4439 // Now that we have the actual prefix and suffix, fix up formatWidth
\r
4440 if (formatWidth > 0) {
\r
4441 formatWidth += positivePrefix.length() + positiveSuffix.length();
\r
4445 private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {
\r
4446 char zeroDigit = PATTERN_ZERO_DIGIT; // '0'
\r
4447 char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'
\r
4448 char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
\r
4449 char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
\r
4450 char percent = PATTERN_PERCENT;
\r
4451 char perMill = PATTERN_PER_MILLE;
\r
4452 char digit = PATTERN_DIGIT; // '#'
\r
4453 char separator = PATTERN_SEPARATOR;
\r
4454 String exponent = String.valueOf(PATTERN_EXPONENT);
\r
4455 char plus = PATTERN_PLUS_SIGN;
\r
4456 char padEscape = PATTERN_PAD_ESCAPE;
\r
4457 char minus = PATTERN_MINUS; //Bug 4212072 [Richard/GCL]
\r
4459 zeroDigit = symbols.getZeroDigit();
\r
4460 sigDigit = symbols.getSignificantDigit();
\r
4461 groupingSeparator = symbols.getGroupingSeparator();
\r
4462 decimalSeparator = symbols.getDecimalSeparator();
\r
4463 percent = symbols.getPercent();
\r
4464 perMill = symbols.getPerMill();
\r
4465 digit = symbols.getDigit();
\r
4466 separator = symbols.getPatternSeparator();
\r
4467 exponent = symbols.getExponentSeparator();
\r
4468 plus = symbols.getPlusSign();
\r
4469 padEscape = symbols.getPadEscape();
\r
4470 minus = symbols.getMinusSign(); //Bug 4212072 [Richard/GCL]
\r
4472 char nineDigit = (char) (zeroDigit + 9);
\r
4474 boolean gotNegative = false;
\r
4477 // Part 0 is the positive pattern. Part 1, if present, is the negative
\r
4479 for (int part=0; part<2 && pos<pattern.length(); ++part) {
\r
4480 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix,
\r
4481 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is
\r
4482 // between the prefix and suffix, and consists of pattern
\r
4483 // characters. In the prefix and suffix, percent, permille, and
\r
4484 // currency symbols are recognized and translated.
\r
4485 int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;
\r
4487 // It's important that we don't change any fields of this object
\r
4488 // prematurely. We set the following variables for the multiplier,
\r
4489 // grouping, etc., and then only change the actual object fields if
\r
4490 // everything parses correctly. This also lets us register
\r
4491 // the data from part 0 and ignore the part 1, except for the
\r
4492 // prefix and suffix.
\r
4493 StringBuffer prefix = new StringBuffer();
\r
4494 StringBuffer suffix = new StringBuffer();
\r
4495 int decimalPos = -1;
\r
4497 int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;
\r
4498 byte groupingCount = -1;
\r
4499 byte groupingCount2 = -1;
\r
4502 int incrementPos = -1;
\r
4503 long incrementVal = 0;
\r
4504 byte expDigits = -1;
\r
4505 boolean expSignAlways = false;
\r
4507 // The affix is either the prefix or the suffix.
\r
4508 StringBuffer affix = prefix;
\r
4513 for (; pos < pattern.length(); ++pos) {
\r
4514 char ch = pattern.charAt(pos);
\r
4515 switch (subpart) {
\r
4516 case 0: // Pattern proper subpart (between prefix & suffix)
\r
4517 // Process the digits, decimal, and grouping characters. We
\r
4518 // record five pieces of information. We expect the digits
\r
4519 // to occur in the pattern ####00.00####, and we record the
\r
4520 // number of left digits, zero (central) digits, and right
\r
4521 // digits. The position of the last grouping character is
\r
4522 // recorded (should be somewhere within the first two blocks
\r
4523 // of characters), as is the position of the decimal point,
\r
4524 // if any (should be in the zero digits). If there is no
\r
4525 // decimal point, then there should be no right digits.
\r
4526 if (ch == digit) {
\r
4527 if (zeroDigitCount > 0 || sigDigitCount > 0) {
\r
4528 ++digitRightCount;
\r
4532 if (groupingCount >= 0 && decimalPos < 0) {
\r
4535 } else if ((ch >= zeroDigit && ch <= nineDigit) ||
\r
4537 if (digitRightCount > 0) {
\r
4538 patternError("Unexpected '" + ch + '\'', pattern);
\r
4540 if (ch == sigDigit) {
\r
4544 if (ch != zeroDigit) {
\r
4545 int p = digitLeftCount + zeroDigitCount
\r
4546 + digitRightCount;
\r
4547 if (incrementPos >= 0) {
\r
4548 while (incrementPos < p) {
\r
4549 incrementVal *= 10;
\r
4555 incrementVal += ch - zeroDigit;
\r
4558 if (groupingCount >= 0 && decimalPos < 0) {
\r
4561 } else if (ch == groupingSeparator) {
\r
4563 process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
\r
4564 (Locale="CH", groupingSeparator == QUOTE)
\r
4567 if (ch == QUOTE && (pos+1) < pattern.length()) {
\r
4568 char after = pattern.charAt(pos+1);
\r
4569 if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {
\r
4570 // A quote outside quotes indicates either the opening
\r
4571 // quote or two quotes, which is a quote literal. That is,
\r
4572 // we have the first quote in 'do' or o''clock.
\r
4573 if (after == QUOTE) {
\r
4575 // Fall through to append(ch)
\r
4577 if (groupingCount < 0) {
\r
4578 subpart = 3; // quoted prefix subpart
\r
4580 // Transition to suffix subpart
\r
4581 subpart = 2; // suffix subpart
\r
4583 sub0Limit = pos--;
\r
4590 if (decimalPos >= 0) {
\r
4591 patternError("Grouping separator after decimal", pattern);
\r
4593 groupingCount2 = groupingCount;
\r
4594 groupingCount = 0;
\r
4595 } else if (ch == decimalSeparator) {
\r
4596 if (decimalPos >= 0) {
\r
4597 patternError("Multiple decimal separators", pattern);
\r
4599 // Intentionally incorporate the digitRightCount,
\r
4600 // even though it is illegal for this to be > 0
\r
4601 // at this point. We check pattern syntax below.
\r
4602 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
\r
4604 if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {
\r
4605 if (expDigits >= 0) {
\r
4606 patternError("Multiple exponential symbols", pattern);
\r
4608 if (groupingCount >= 0) {
\r
4609 patternError("Grouping separator in exponential", pattern);
\r
4611 pos += exponent.length();
\r
4612 // Check for positive prefix
\r
4613 if (pos < pattern.length()
\r
4614 && pattern.charAt(pos) == plus) {
\r
4615 expSignAlways = true;
\r
4618 // Use lookahead to parse out the exponential part of the
\r
4619 // pattern, then jump into suffix subpart.
\r
4621 while (pos < pattern.length() &&
\r
4622 pattern.charAt(pos) == zeroDigit) {
\r
4627 // 1. Require at least one mantissa pattern digit
\r
4628 // 2. Disallow "#+ @" in mantissa
\r
4629 // 3. Require at least one exponent pattern digit
\r
4630 if (((digitLeftCount + zeroDigitCount) < 1 &&
\r
4631 (sigDigitCount + digitRightCount) < 1) ||
\r
4632 (sigDigitCount > 0 && digitLeftCount > 0) ||
\r
4634 patternError("Malformed exponential", pattern);
\r
4637 // Transition to suffix subpart
\r
4638 subpart = 2; // suffix subpart
\r
4640 sub0Limit = pos--; // backup: for() will increment
\r
4644 case 1: // Prefix subpart
\r
4645 case 2: // Suffix subpart
\r
4646 // Process the prefix / suffix characters
\r
4647 // Process unquoted characters seen in prefix or suffix
\r
4650 // Several syntax characters implicitly begins the
\r
4651 // next subpart if we are in the prefix; otherwise
\r
4652 // they are illegal if unquoted.
\r
4653 if (ch == digit ||
\r
4654 ch == groupingSeparator ||
\r
4655 ch == decimalSeparator ||
\r
4656 (ch >= zeroDigit && ch <= nineDigit) ||
\r
4658 // Any of these characters implicitly begins the
\r
4659 // next subpart if we are in the prefix
\r
4660 if (subpart == 1) { // prefix subpart
\r
4661 subpart = 0; // pattern proper subpart
\r
4662 sub0Start = pos--; // Reprocess this character
\r
4664 } else if (ch == QUOTE) {
\r
4666 process the Localized pattern like "'Fr. '#'##0.05;'Fr.-'#'##0.05"
\r
4667 (Locale="CH", groupingSeparator == QUOTE)
\r
4670 // A quote outside quotes indicates either the opening
\r
4671 // quote or two quotes, which is a quote literal. That is,
\r
4672 // we have the first quote in 'do' or o''clock.
\r
4673 if ((pos+1) < pattern.length() &&
\r
4674 pattern.charAt(pos+1) == QUOTE) {
\r
4678 subpart += 2; // open quote
\r
4682 patternError("Unquoted special character '" + ch + '\'', pattern);
\r
4683 } else if (ch == CURRENCY_SIGN) {
\r
4684 // Use lookahead to determine if the currency sign is
\r
4685 // doubled or not.
\r
4686 boolean doubled = (pos + 1) < pattern.length() &&
\r
4687 pattern.charAt(pos + 1) == CURRENCY_SIGN;
\r
4689 To meet the need of expandAffix(String, StirngBuffer)
\r
4693 ++pos; // Skip over the doubled character
\r
4694 affix.append(ch); // append two: one here, one below
\r
4695 if ((pos + 1) < pattern.length() &&
\r
4696 pattern.charAt(pos + 1) == CURRENCY_SIGN) {
\r
4697 ++pos; // Skip over the tripled character
\r
4698 affix.append(ch); // append again
\r
4699 currencySignCount = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;
\r
4701 currencySignCount = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;
\r
4704 currencySignCount = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;
\r
4706 // Fall through to append(ch)
\r
4707 } else if (ch == QUOTE) {
\r
4708 // A quote outside quotes indicates either the opening
\r
4709 // quote or two quotes, which is a quote literal. That is,
\r
4710 // we have the first quote in 'do' or o''clock.
\r
4711 if((pos+1) < pattern.length()&&
\r
4712 pattern.charAt(pos+1)==QUOTE){
\r
4714 affix.append(ch); // append two: one here, one below
\r
4716 subpart += 2; // open quote
\r
4718 // Fall through to append(ch)
\r
4719 } else if (ch == separator) {
\r
4720 // Don't allow separators in the prefix, and don't allow
\r
4721 // separators in the second pattern (part == 1).
\r
4722 if (subpart == 1 || part == 1) {
\r
4723 patternError("Unquoted special character '" + ch + '\'', pattern);
\r
4725 sub2Limit = pos++;
\r
4726 break PARTLOOP; // Go to next part
\r
4727 } else if (ch == percent || ch == perMill) {
\r
4728 // Next handle characters which are appended directly.
\r
4729 if (multpl != 1) {
\r
4730 patternError("Too many percent/permille characters", pattern);
\r
4732 multpl = (ch == percent) ? 100 : 1000;
\r
4733 // Convert to non-localized pattern
\r
4734 ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;
\r
4735 // Fall through to append(ch)
\r
4736 } else if (ch == minus) {
\r
4737 // Convert to non-localized pattern
\r
4738 ch = PATTERN_MINUS;
\r
4739 // Fall through to append(ch)
\r
4740 } else if (ch == padEscape) {
\r
4741 if (padPos >= 0) {
\r
4742 patternError("Multiple pad specifiers", pattern);
\r
4744 if ((pos+1) == pattern.length()) {
\r
4745 patternError("Invalid pad specifier", pattern);
\r
4747 padPos = pos++; // Advance past pad char
\r
4748 padChar = pattern.charAt(pos);
\r
4753 case 3: // Prefix subpart, in quote
\r
4754 case 4: // Suffix subpart, in quote
\r
4755 // A quote within quotes indicates either the closing
\r
4756 // quote or two quotes, which is a quote literal. That is,
\r
4757 // we have the second quote in 'do' or 'don''t'.
\r
4758 if (ch == QUOTE) {
\r
4759 if ((pos+1) < pattern.length() &&
\r
4760 pattern.charAt(pos+1) == QUOTE) {
\r
4764 subpart -= 2; // close quote
\r
4766 // Fall through to append(ch)
\r
4768 // NOTE: In ICU 2.2 there was code here to parse quoted
\r
4769 // percent and permille characters _within quotes_ and give
\r
4770 // them special meaning. This is incorrect, since quoted
\r
4771 // characters are literals without special meaning.
\r
4777 if (subpart == 3 || subpart == 4) {
\r
4778 patternError("Unterminated quote", pattern);
\r
4781 if (sub0Limit == 0) {
\r
4782 sub0Limit = pattern.length();
\r
4785 if (sub2Limit == 0) {
\r
4786 sub2Limit = pattern.length();
\r
4789 /* Handle patterns with no '0' pattern character. These patterns
\r
4790 * are legal, but must be recodified to make sense. "##.###" ->
\r
4791 * "#0.###". ".###" -> ".0##".
\r
4793 * We allow patterns of the form "####" to produce a zeroDigitCount
\r
4794 * of zero (got that?); although this seems like it might make it
\r
4795 * possible for format() to produce empty strings, format() checks
\r
4796 * for this condition and outputs a zero digit in this situation.
\r
4797 * Having a zeroDigitCount of zero yields a minimum integer digits
\r
4798 * of zero, which allows proper round-trip patterns. We don't want
\r
4799 * "#" to become "#0" when toPattern() is called (even though that's
\r
4800 * what it really is, semantically).
\r
4802 if (zeroDigitCount == 0 && sigDigitCount == 0 &&
\r
4803 digitLeftCount > 0 && decimalPos >= 0) {
\r
4804 // Handle "###.###" and "###." and ".###"
\r
4805 int n = decimalPos;
\r
4806 if (n == 0) ++n; // Handle ".###"
\r
4807 digitRightCount = digitLeftCount - n;
\r
4808 digitLeftCount = n - 1;
\r
4809 zeroDigitCount = 1;
\r
4812 // Do syntax checking on the digits, decimal points, and quotes.
\r
4813 if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) ||
\r
4814 (decimalPos >= 0 &&
\r
4815 (sigDigitCount > 0 ||
\r
4816 decimalPos < digitLeftCount ||
\r
4817 decimalPos > (digitLeftCount + zeroDigitCount))) ||
\r
4818 groupingCount == 0 || groupingCount2 == 0 ||
\r
4819 (sigDigitCount > 0 && zeroDigitCount > 0) ||
\r
4820 subpart > 2) { // subpart > 2 == unmatched quote
\r
4821 patternError("Malformed pattern", pattern);
\r
4824 // Make sure pad is at legal position before or after affix.
\r
4825 if (padPos >= 0) {
\r
4826 if (padPos == start) {
\r
4827 padPos = PAD_BEFORE_PREFIX;
\r
4828 } else if (padPos+2 == sub0Start) {
\r
4829 padPos = PAD_AFTER_PREFIX;
\r
4830 } else if (padPos == sub0Limit) {
\r
4831 padPos = PAD_BEFORE_SUFFIX;
\r
4832 } else if (padPos+2 == sub2Limit) {
\r
4833 padPos = PAD_AFTER_SUFFIX;
\r
4835 patternError("Illegal pad position", pattern);
\r
4840 // Set negative affixes temporarily to match the positive
\r
4841 // affixes. Fix this up later after processing both parts.
\r
4843 To meet the need of expandAffix(String, StirngBuffer)
\r
4846 posPrefixPattern = negPrefixPattern = prefix.toString();
\r
4847 posSuffixPattern = negSuffixPattern = suffix.toString();
\r
4849 useExponentialNotation = (expDigits >= 0);
\r
4850 if (useExponentialNotation) {
\r
4851 minExponentDigits = expDigits;
\r
4852 exponentSignAlwaysShown = expSignAlways;
\r
4854 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
\r
4855 // The effectiveDecimalPos is the position the decimal is at or
\r
4856 // would be at if there is no decimal. Note that if
\r
4857 // decimalPos<0, then digitTotalCount == digitLeftCount +
\r
4858 // zeroDigitCount.
\r
4859 int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
\r
4860 boolean useSigDig = (sigDigitCount > 0);
\r
4861 setSignificantDigitsUsed(useSigDig);
\r
4863 setMinimumSignificantDigits(sigDigitCount);
\r
4864 setMaximumSignificantDigits(sigDigitCount + digitRightCount);
\r
4866 int minInt = effectiveDecimalPos - digitLeftCount;
\r
4867 setMinimumIntegerDigits(minInt);
\r
4868 /*Upper limit on integer and fraction digits for a Java double
\r
4871 setMaximumIntegerDigits(useExponentialNotation
\r
4872 ? digitLeftCount + minInt : DOUBLE_INTEGER_DIGITS);
\r
4873 setMaximumFractionDigits(decimalPos >= 0
\r
4874 ? (digitTotalCount - decimalPos) : 0);
\r
4875 setMinimumFractionDigits(decimalPos >= 0
\r
4876 ? (digitLeftCount + zeroDigitCount - decimalPos) : 0);
\r
4878 setGroupingUsed(groupingCount > 0);
\r
4879 this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
\r
4880 this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)
\r
4881 ? groupingCount2 : 0;
\r
4882 this.multiplier = multpl;
\r
4883 setDecimalSeparatorAlwaysShown(decimalPos == 0
\r
4884 || decimalPos == digitTotalCount);
\r
4885 if (padPos >= 0) {
\r
4886 padPosition = padPos;
\r
4887 formatWidth = sub0Limit - sub0Start; // to be fixed up below
\r
4892 if (incrementVal != 0) {
\r
4893 // BigDecimal scale cannot be negative (even though
\r
4894 // this makes perfect sense), so we need to handle this.
\r
4895 int scale = incrementPos - effectiveDecimalPos;
\r
4896 roundingIncrementICU =
\r
4897 BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);
\r
4899 roundingIncrementICU =
\r
4900 roundingIncrementICU.movePointRight(-scale);
\r
4902 setRoundingDouble();
\r
4903 roundingMode = BigDecimal.ROUND_HALF_EVEN;
\r
4905 setRoundingIncrement((BigDecimal)null);
\r
4909 To meet the need of expandAffix(String, StirngBuffer)
\r
4912 negPrefixPattern = prefix.toString();
\r
4913 negSuffixPattern = suffix.toString();
\r
4914 gotNegative = true;
\r
4919 Process the empty pattern
\r
4922 if (pattern.length() == 0) {
\r
4923 posPrefixPattern = posSuffixPattern = "";
\r
4924 setMinimumIntegerDigits(0);
\r
4925 setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
\r
4926 setMinimumFractionDigits(0);
\r
4927 setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
\r
4930 // If there was no negative pattern, or if the negative pattern is
\r
4931 // identical to the positive pattern, then prepend the minus sign to the
\r
4932 // positive pattern to form the negative pattern.
\r
4934 To meet the need of expandAffix(String, StirngBuffer)
\r
4937 if (!gotNegative ||
\r
4938 (negPrefixPattern.equals(posPrefixPattern)
\r
4939 && negSuffixPattern.equals(posSuffixPattern))) {
\r
4940 negSuffixPattern = posSuffixPattern;
\r
4941 negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
\r
4943 setLocale(null, null);
\r
4944 // save the pattern
\r
4945 formatPattern = pattern;
\r
4946 // initialize currencyPluralInfo if needed
\r
4947 if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT &&
\r
4948 currencyPluralInfo == null) {
\r
4949 currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());
\r
4954 * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.
\r
4956 private void setRoundingDouble() {
\r
4957 if (roundingIncrementICU == null) {
\r
4958 roundingDouble = 0.0d;
\r
4959 roundingDoubleReciprocal = 0.0d;
\r
4961 roundingDouble = roundingIncrementICU.doubleValue();
\r
4962 setRoundingDoubleReciprocal(BigDecimal.ONE.divide(roundingIncrementICU,BigDecimal.ROUND_HALF_EVEN).doubleValue());
\r
4966 private void patternError(String msg, String pattern) {
\r
4967 throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');
\r
4970 /*Rewrite the following 4 "set" methods
\r
4971 Upper limit on integer and fraction digits for a Java double
\r
4975 * Sets the maximum number of digits allowed in the integer portion of a
\r
4976 * number. This override limits the integer digit count to 309.
\r
4977 * @see NumberFormat#setMaximumIntegerDigits
\r
4980 public void setMaximumIntegerDigits(int newValue) {
\r
4981 super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
\r
4985 * Sets the minimum number of digits allowed in the integer portion of a
\r
4986 * number. This override limits the integer digit count to 309.
\r
4987 * @see NumberFormat#setMinimumIntegerDigits
\r
4990 public void setMinimumIntegerDigits(int newValue) {
\r
4991 super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
\r
4995 * Returns the minimum number of significant digits that will be
\r
4996 * displayed. This value has no effect unless areSignificantDigitsUsed()
\r
4998 * @return the fewest significant digits that will be shown
\r
5001 public int getMinimumSignificantDigits() {
\r
5002 return minSignificantDigits;
\r
5006 * Returns the maximum number of significant digits that will be
\r
5007 * displayed. This value has no effect unless areSignificantDigitsUsed()
\r
5009 * @return the most significant digits that will be shown
\r
5012 public int getMaximumSignificantDigits() {
\r
5013 return maxSignificantDigits;
\r
5017 * Sets the minimum number of significant digits that will be
\r
5018 * displayed. If <code>min</code> is less than one then it is set
\r
5019 * to one. If the maximum significant digits count is less than
\r
5020 * <code>min</code>, then it is set to <code>min</code>. This
\r
5021 * value has no effect unless areSignificantDigitsUsed() returns true.
\r
5022 * @param min the fewest significant digits to be shown
\r
5025 public void setMinimumSignificantDigits(int min) {
\r
5029 // pin max sig dig to >= min
\r
5030 int max = Math.max(maxSignificantDigits, min);
\r
5031 minSignificantDigits = min;
\r
5032 maxSignificantDigits = max;
\r
5036 * Sets the maximum number of significant digits that will be
\r
5037 * displayed. If <code>max</code> is less than one then it is set
\r
5038 * to one. If the minimum significant digits count is greater
\r
5039 * than <code>max</code>, then it is set to <code>max</code>. This
\r
5040 * value has no effect unless areSignificantDigitsUsed() returns true.
\r
5041 * @param max the most significant digits to be shown
\r
5044 public void setMaximumSignificantDigits(int max) {
\r
5048 // pin min sig dig to 1..max
\r
5049 int min = Math.min(minSignificantDigits, max);
\r
5050 minSignificantDigits = min;
\r
5051 maxSignificantDigits = max;
\r
5055 * Returns true if significant digits are in use or false if
\r
5056 * integer and fraction digit counts are in use.
\r
5057 * @return true if significant digits are in use
\r
5060 public boolean areSignificantDigitsUsed() {
\r
5061 return useSignificantDigits;
\r
5065 * Sets whether significant digits are in use, or integer and
\r
5066 * fraction digit counts are in use.
\r
5067 * @param useSignificantDigits true to use significant digits, or
\r
5068 * false to use integer and fraction digit counts
\r
5071 public void setSignificantDigitsUsed(boolean useSignificantDigits) {
\r
5072 this.useSignificantDigits = useSignificantDigits;
\r
5076 * Sets the <tt>Currency</tt> object used to display currency
\r
5077 * amounts. This takes effect immediately, if this format is a
\r
5078 * currency format. If this format is not a currency format, then
\r
5079 * the currency object is used if and when this object becomes a
\r
5080 * currency format through the application of a new pattern.
\r
5081 * @param theCurrency new currency object to use. Must not be
\r
5085 public void setCurrency(Currency theCurrency) {
\r
5086 // If we are a currency format, then modify our affixes to
\r
5087 // encode the currency symbol for the given currency in our
\r
5088 // locale, and adjust the decimal digits and rounding for the
\r
5089 // given currency.
\r
5091 super.setCurrency(theCurrency);
\r
5092 if (theCurrency != null) {
\r
5093 boolean[] isChoiceFormat = new boolean[1];
\r
5094 String s = theCurrency.getName(symbols.getULocale(),
\r
5095 Currency.SYMBOL_NAME,
\r
5097 symbols.setCurrencySymbol(s);
\r
5098 symbols.setInternationalCurrencySymbol(theCurrency.getCurrencyCode());
\r
5101 if (currencySignCount > 0) {
\r
5102 if (theCurrency != null) {
\r
5103 setRoundingIncrement(theCurrency.getRoundingIncrement());
\r
5104 int d = theCurrency.getDefaultFractionDigits();
\r
5105 setMinimumFractionDigits(d);
\r
5106 setMaximumFractionDigits(d);
\r
5108 expandAffixes(null);
\r
5113 * Returns the currency in effect for this formatter. Subclasses
\r
5114 * should override this method as needed. Unlike getCurrency(),
\r
5115 * this method should never return null.
\r
5117 * @deprecated This API is ICU internal only.
\r
5119 protected Currency getEffectiveCurrency() {
\r
5120 Currency c = getCurrency();
\r
5122 c = Currency.getInstance(symbols.getInternationalCurrencySymbol());
\r
5128 * Sets the maximum number of digits allowed in the fraction portion of a
\r
5129 * number. This override limits the fraction digit count to 340.
\r
5130 * @see NumberFormat#setMaximumFractionDigits
\r
5133 public void setMaximumFractionDigits(int newValue) {
\r
5134 super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
\r
5138 * Sets the minimum number of digits allowed in the fraction portion of a
\r
5139 * number. This override limits the fraction digit count to 340.
\r
5140 * @see NumberFormat#setMinimumFractionDigits
\r
5143 public void setMinimumFractionDigits(int newValue) {
\r
5144 super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
\r
5148 * Sets whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
\r
5149 * The default value is false.
\r
5150 * @param value true if {@link #parse(String, ParsePosition)} method returns
\r
5154 public void setParseBigDecimal(boolean value) {
\r
5155 parseBigDecimal = value;
\r
5159 * Returns whether {@link #parse(String, ParsePosition)} method returns BigDecimal.
\r
5160 * @return true if {@link #parse(String, ParsePosition)} method returns BigDecimal.
\r
5163 public boolean isParseBigDecimal() {
\r
5164 return parseBigDecimal;
\r
5167 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
5169 private void writeObject(ObjectOutputStream stream) throws IOException {
\r
5170 // Doug, do we need this anymore?
\r
5171 // if (roundingIncrementICU != null) {
\r
5172 // roundingIncrement = roundingIncrementICU.toBigDecimal();
\r
5176 // Format.Field instances are not serializable. When formatToCharacterIterator
\r
5177 // is called, attributes (ArrayList) stores FieldPosition instances with
\r
5178 // NumberFormat.Field. Because NumberFormat.Field is not serializable, we need
\r
5179 // to clear the contents of the list when writeObject is called. We could remove
\r
5180 // the field or make it transient, but it will break serialization compatibility.
\r
5181 attributes.clear();
\r
5183 stream.defaultWriteObject();
\r
5188 * First, read the default serializable fields from the stream. Then
\r
5189 * if <code>serialVersionOnStream</code> is less than 1, indicating that
\r
5190 * the stream was written by JDK 1.1, initialize <code>useExponentialNotation</code>
\r
5191 * to false, since it was not present in JDK 1.1.
\r
5192 * Finally, set serialVersionOnStream back to the maximum allowed value so that
\r
5193 * default serialization will work properly if this object is streamed out again.
\r
5195 private void readObject(ObjectInputStream stream)
\r
5196 throws IOException, ClassNotFoundException
\r
5198 stream.defaultReadObject();
\r
5199 /*Bug 4185761 validate fields
\r
5202 // We only need to check the maximum counts because NumberFormat
\r
5203 // .readObject has already ensured that the maximum is greater than the
\r
5205 /*Commented for compatibility with previous version, and reserved for further use
\r
5206 if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
\r
5207 getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
\r
5208 throw new InvalidObjectException("Digit count out of range");
\r
5210 /* Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and maximumFractionDigits
\r
5211 * to DOUBLE_FRACTION_DIGITS
\r
5213 if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {
\r
5214 setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
\r
5216 if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
\r
5217 setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
\r
5219 if (serialVersionOnStream < 2) {
\r
5220 exponentSignAlwaysShown = false;
\r
5221 setInternalRoundingIncrement(null);
\r
5222 setRoundingDouble();
\r
5223 roundingMode = BigDecimal.ROUND_HALF_EVEN;
\r
5226 padPosition = PAD_BEFORE_PREFIX;
\r
5227 if (serialVersionOnStream < 1) {
\r
5228 // Didn't have exponential fields
\r
5229 useExponentialNotation = false;
\r
5232 if (serialVersionOnStream < 3) {
\r
5233 // Versions prior to 3 do not store a currency object.
\r
5234 // Create one to match the DecimalFormatSymbols object.
\r
5235 setCurrencyForSymbols();
\r
5237 serialVersionOnStream = currentSerialVersion;
\r
5238 digitList = new DigitList();
\r
5240 //#if defined(FOUNDATION10)
\r
5242 if (roundingIncrement != null) {
\r
5243 setInternalRoundingIncrement(new BigDecimal(roundingIncrement));
\r
5244 setRoundingDouble();
\r
5250 private void setInternalRoundingIncrement(BigDecimal value) {
\r
5251 roundingIncrementICU = value;
\r
5252 //#if defined(FOUNDATION10)
\r
5254 roundingIncrement = value == null ? null : value.toBigDecimal();
\r
5258 //----------------------------------------------------------------------
\r
5259 // INSTANCE VARIABLES
\r
5260 //----------------------------------------------------------------------
\r
5262 private transient DigitList digitList = new DigitList();
\r
5265 * The symbol used as a prefix when formatting positive numbers, e.g. "+".
\r
5268 * @see #getPositivePrefix
\r
5270 private String positivePrefix = "";
\r
5273 * The symbol used as a suffix when formatting positive numbers.
\r
5274 * This is often an empty string.
\r
5277 * @see #getPositiveSuffix
\r
5279 private String positiveSuffix = "";
\r
5282 * The symbol used as a prefix when formatting negative numbers, e.g. "-".
\r
5285 * @see #getNegativePrefix
\r
5287 private String negativePrefix = "-";
\r
5290 * The symbol used as a suffix when formatting negative numbers.
\r
5291 * This is often an empty string.
\r
5294 * @see #getNegativeSuffix
\r
5296 private String negativeSuffix = "";
\r
5299 * The prefix pattern for non-negative numbers. This variable corresponds
\r
5300 * to <code>positivePrefix</code>.
\r
5302 * <p>This pattern is expanded by the method <code>expandAffix()</code> to
\r
5303 * <code>positivePrefix</code> to update the latter to reflect changes in
\r
5304 * <code>symbols</code>. If this variable is <code>null</code> then
\r
5305 * <code>positivePrefix</code> is taken as a literal value that does not
\r
5306 * change when <code>symbols</code> changes. This variable is always
\r
5307 * <code>null</code> for <code>DecimalFormat</code> objects older than
\r
5308 * stream version 2 restored from stream.
\r
5313 private String posPrefixPattern;
\r
5316 * The suffix pattern for non-negative numbers. This variable corresponds
\r
5317 * to <code>positiveSuffix</code>. This variable is analogous to
\r
5318 * <code>posPrefixPattern</code>; see that variable for further
\r
5324 private String posSuffixPattern;
\r
5327 * The prefix pattern for negative numbers. This variable corresponds
\r
5328 * to <code>negativePrefix</code>. This variable is analogous to
\r
5329 * <code>posPrefixPattern</code>; see that variable for further
\r
5335 private String negPrefixPattern;
\r
5338 * The suffix pattern for negative numbers. This variable corresponds
\r
5339 * to <code>negativeSuffix</code>. This variable is analogous to
\r
5340 * <code>posPrefixPattern</code>; see that variable for further
\r
5346 private String negSuffixPattern;
\r
5351 * Formatter for ChoiceFormat-based currency names. If this field
\r
5352 * is not null, then delegate to it to format currency symbols.
\r
5355 private ChoiceFormat currencyChoice;
\r
5358 * The multiplier for use in percent, permill, etc.
\r
5361 * @see #getMultiplier
\r
5363 private int multiplier = 1;
\r
5366 * The number of digits between grouping separators in the integer
\r
5367 * portion of a number. Must be greater than 0 if
\r
5368 * <code>NumberFormat.groupingUsed</code> is true.
\r
5371 * @see #getGroupingSize
\r
5372 * @see NumberFormat#isGroupingUsed
\r
5374 private byte groupingSize = 3; // invariant, > 0 if useThousands
\r
5378 * The secondary grouping size. This is only used for Hindi
\r
5379 * numerals, which use a primary grouping of 3 and a secondary
\r
5380 * grouping of 2, e.g., "12,34,567". If this value is less than
\r
5381 * 1, then secondary grouping is equal to the primary grouping.
\r
5384 private byte groupingSize2 = 0;
\r
5387 * If true, forces the decimal separator to always appear in a formatted
\r
5388 * number, even if the fractional part of the number is zero.
\r
5391 * @see #isDecimalSeparatorAlwaysShown
\r
5393 private boolean decimalSeparatorAlwaysShown = false;
\r
5397 * The <code>DecimalFormatSymbols</code> object used by this format.
\r
5398 * It contains the symbols used to format numbers, e.g. the grouping separator,
\r
5399 * decimal separator, and so on.
\r
5402 * @see #setDecimalFormatSymbols
\r
5403 * @see DecimalFormatSymbols
\r
5405 private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
\r
5408 * True to use significant digits rather than integer and fraction
\r
5413 private boolean useSignificantDigits = false;
\r
5416 * The minimum number of significant digits to show. Must be >= 1
\r
5417 * and <= maxSignificantDigits. Ignored unless
\r
5418 * useSignificantDigits == true.
\r
5422 private int minSignificantDigits = 1;
\r
5425 * The maximum number of significant digits to show. Must be >=
\r
5426 * minSignficantDigits. Ignored unless useSignificantDigits ==
\r
5431 private int maxSignificantDigits = 6;
\r
5434 * True to force the use of exponential (i.e. scientific) notation when formatting
\r
5437 * Note that the JDK 1.2 public API provides no way to set this field,
\r
5438 * even though it is supported by the implementation and the stream format.
\r
5439 * The intent is that this will be added to the API in the future.
\r
5443 private boolean useExponentialNotation; // Newly persistent in JDK 1.2
\r
5446 * The minimum number of digits used to display the exponent when a number is
\r
5447 * formatted in exponential notation. This field is ignored if
\r
5448 * <code>useExponentialNotation</code> is not true.
\r
5450 * Note that the JDK 1.2 public API provides no way to set this field,
\r
5451 * even though it is supported by the implementation and the stream format.
\r
5452 * The intent is that this will be added to the API in the future.
\r
5456 private byte minExponentDigits; // Newly persistent in JDK 1.2
\r
5460 * If true, the exponent is always prefixed with either the plus
\r
5461 * sign or the minus sign. Otherwise, only negative exponents are
\r
5462 * prefixed with the minus sign. This has no effect unless
\r
5463 * <code>useExponentialNotation</code> is true.
\r
5465 * @since AlphaWorks NumberFormat
\r
5467 private boolean exponentSignAlwaysShown = false;
\r
5469 //#if defined(FOUNDATION10)
\r
5473 * The value to which numbers are rounded during formatting. For example,
\r
5474 * if the rounding increment is 0.05, then 13.371 would be formatted as
\r
5475 * 13.350, assuming 3 fraction digits. Has the value <code>null</code> if
\r
5476 * rounding is not in effect, or a positive value if rounding is in effect.
\r
5477 * Default value <code>null</code>.
\r
5479 * @since AlphaWorks NumberFormat
\r
5481 // Note: this is kept in sync with roundingIncrementICU.
\r
5482 // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal
\r
5483 private java.math.BigDecimal roundingIncrement = null;
\r
5488 * The value to which numbers are rounded during formatting. For example,
\r
5489 * if the rounding increment is 0.05, then 13.371 would be formatted as
\r
5490 * 13.350, assuming 3 fraction digits. Has the value <code>null</code> if
\r
5491 * rounding is not in effect, or a positive value if rounding is in effect.
\r
5492 * Default value <code>null</code>.
\r
5493 * WARNING: the roundingIncrement value is the one serialized.
\r
5495 * @since AlphaWorks NumberFormat
\r
5497 private transient BigDecimal roundingIncrementICU = null;
\r
5501 * The rounding increment as a double. If this value is <= 0, then no
\r
5502 * rounding is done. This value is
\r
5503 * <code>roundingIncrementICU.doubleValue()</code>. Default value 0.0.
\r
5505 private transient double roundingDouble = 0.0;
\r
5509 * If the roundingDouble is the reciprocal of an integer (the most common case!),
\r
5510 * this is set to be that integer. Otherwise it is 0.0.
\r
5512 private transient double roundingDoubleReciprocal = 0.0;
\r
5516 * The rounding mode. This value controls any rounding operations which
\r
5517 * occur when applying a rounding increment or when reducing the number of
\r
5518 * fraction digits to satisfy a maximum fraction digits limit. The value
\r
5519 * may assume any of the <code>BigDecimal</code> rounding mode values.
\r
5520 * Default value <code>BigDecimal.ROUND_HALF_EVEN</code>.
\r
5522 * @since AlphaWorks NumberFormat
\r
5524 private int roundingMode = BigDecimal.ROUND_HALF_EVEN;
\r
5528 * Operations on <code>BigDecimal</code> numbers are controlled by a
\r
5529 * {@link MathContext} object, which provides the context (precision and
\r
5530 * other information) for the operation. The default <code>MathContext</code>
\r
5531 * settings are <code>digits=0, form=PLAIN, lostDigits=false,
\r
5532 * roundingMode=ROUND_HALF_UP</code>; these settings perform fixed point
\r
5533 * arithmetic with unlimited precision, as defined for the original BigDecimal
\r
5534 * class in Java 1.1 and Java 1.2
\r
5536 private MathContext mathContext = new MathContext(0, MathContext.PLAIN); // context for plain unlimited math
\r
5540 * The padded format width, or zero if there is no padding. Must
\r
5541 * be >= 0. Default value zero.
\r
5543 * @since AlphaWorks NumberFormat
\r
5545 private int formatWidth = 0;
\r
5549 * The character used to pad the result of format to
\r
5550 * <code>formatWidth</code>, if padding is in effect. Default value ' '.
\r
5552 * @since AlphaWorks NumberFormat
\r
5554 private char pad = ' ';
\r
5558 * The position in the string at which the <code>pad</code> character
\r
5559 * will be inserted, if padding is in effect. Must have a value from
\r
5560 * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>.
\r
5561 * Default value <code>PAD_BEFORE_PREFIX</code>.
\r
5563 * @since AlphaWorks NumberFormat
\r
5565 private int padPosition = PAD_BEFORE_PREFIX;
\r
5568 * True if {@link #parse(String, ParsePosition)} to return BigDecimal
\r
5569 * rather than Long, Double or BigDecimal except special values.
\r
5570 * This property is introduced for J2SE 5 compatibility support.
\r
5573 * @see #setParseBigDecimal(boolean)
\r
5574 * @see #isParseBigDecimal()
\r
5576 private boolean parseBigDecimal = false;
\r
5578 //----------------------------------------------------------------------
\r
5580 static final int currentSerialVersion = 3;
\r
5583 * The internal serial version which says which version was written
\r
5584 * Possible values are:
\r
5586 * <li><b>0</b> (default): versions before JDK 1.2
\r
5587 * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields
\r
5588 * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
\r
5589 * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth,
\r
5590 * pad, padPosition, exponentSignAlwaysShown, roundingIncrement.
\r
5591 * <li><b>3</b>: ICU 2.2. Adds currency object.
\r
5594 private int serialVersionOnStream = currentSerialVersion;
\r
5596 //----------------------------------------------------------------------
\r
5598 //----------------------------------------------------------------------
\r
5602 * Constant for <code>getPadPosition()</code> and
\r
5603 * <code>setPadPosition()</code> specifying pad characters inserted before
\r
5605 * @see #setPadPosition
\r
5606 * @see #getPadPosition
\r
5607 * @see #PAD_AFTER_PREFIX
\r
5608 * @see #PAD_BEFORE_SUFFIX
\r
5609 * @see #PAD_AFTER_SUFFIX
\r
5612 public static final int PAD_BEFORE_PREFIX = 0;
\r
5616 * Constant for <code>getPadPosition()</code> and
\r
5617 * <code>setPadPosition()</code> specifying pad characters inserted after
\r
5619 * @see #setPadPosition
\r
5620 * @see #getPadPosition
\r
5621 * @see #PAD_BEFORE_PREFIX
\r
5622 * @see #PAD_BEFORE_SUFFIX
\r
5623 * @see #PAD_AFTER_SUFFIX
\r
5626 public static final int PAD_AFTER_PREFIX = 1;
\r
5630 * Constant for <code>getPadPosition()</code> and
\r
5631 * <code>setPadPosition()</code> specifying pad characters inserted before
\r
5633 * @see #setPadPosition
\r
5634 * @see #getPadPosition
\r
5635 * @see #PAD_BEFORE_PREFIX
\r
5636 * @see #PAD_AFTER_PREFIX
\r
5637 * @see #PAD_AFTER_SUFFIX
\r
5640 public static final int PAD_BEFORE_SUFFIX = 2;
\r
5644 * Constant for <code>getPadPosition()</code> and
\r
5645 * <code>setPadPosition()</code> specifying pad characters inserted after
\r
5647 * @see #setPadPosition
\r
5648 * @see #getPadPosition
\r
5649 * @see #PAD_BEFORE_PREFIX
\r
5650 * @see #PAD_AFTER_PREFIX
\r
5651 * @see #PAD_BEFORE_SUFFIX
\r
5654 public static final int PAD_AFTER_SUFFIX = 3;
\r
5656 // Constants for characters used in programmatic (unlocalized) patterns.
\r
5657 private static final char PATTERN_ZERO_DIGIT = '0';
\r
5658 private static final char PATTERN_GROUPING_SEPARATOR = ',';
\r
5659 private static final char PATTERN_DECIMAL_SEPARATOR = '.';
\r
5660 private static final char PATTERN_DIGIT = '#';
\r
5661 static final char PATTERN_SIGNIFICANT_DIGIT = '@';
\r
5662 static final char PATTERN_EXPONENT = 'E'; // [NEW]
\r
5663 static final char PATTERN_PLUS_SIGN = '+'; // [NEW]
\r
5666 private static final char PATTERN_PER_MILLE = '\u2030';
\r
5667 private static final char PATTERN_PERCENT = '%';
\r
5668 static final char PATTERN_PAD_ESCAPE = '*'; // [NEW]
\r
5670 To meet the need of expandAffix(String, StirngBuffer)
\r
5673 private static final char PATTERN_MINUS = '-'; //[Richard/GCL]
\r
5676 private static final char PATTERN_SEPARATOR = ';';
\r
5678 // Pad escape is package private to allow access by DecimalFormatSymbols.
\r
5679 // Also plus sign. Also exponent.
\r
5682 * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
\r
5683 * is used in patterns and substitued with either the currency symbol,
\r
5684 * or if it is doubled, with the international currency symbol. If the
\r
5685 * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
\r
5686 * replaced with the monetary decimal separator.
\r
5688 * The CURRENCY_SIGN is not localized.
\r
5690 private static final char CURRENCY_SIGN = '\u00A4';
\r
5692 private static final char QUOTE = '\'';
\r
5694 /* Upper limit on integer and fraction digits for a Java double
\r
5697 static final int DOUBLE_INTEGER_DIGITS = 309;
\r
5698 static final int DOUBLE_FRACTION_DIGITS = 340;
\r
5701 * When someone turns on scientific mode, we assume that more than this
\r
5702 * number of digits is due to flipping from some other mode that didn't
\r
5703 * restrict the maximum, and so we force 1 integer digit. We don't bother
\r
5704 * to track and see if someone is using exponential notation with more than
\r
5705 * this number, it wouldn't make sense anyway, and this is just to make sure
\r
5706 * that someone turning on scientific mode with default settings doesn't
\r
5707 * end up with lots of zeroes.
\r
5709 static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;
\r
5711 //#if defined(FOUNDATION10)
\r
5712 //## // we're not compatible with other versions, since we have no java.math.BigDecimal field
\r
5713 //## private static final long serialVersionUID = 2;
\r
5715 // Proclaim JDK 1.1 serial compatibility.
\r
5716 private static final long serialVersionUID = 864413376551465018L;
\r
5719 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
5721 private ArrayList attributes = new ArrayList();
\r
5725 * Following are used in currency format
\r
5728 // triple currency sign char array
\r
5729 private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};
\r
5730 // triple currency sign string
\r
5731 private static final String tripleCurrencyStr = new String(tripleCurrencySign);
\r
5733 // default currency plural pattern char array
\r
5734 private static final char[] defaultCurrencyPluralPatternChar = {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};
\r
5735 // default currency plural pattern string
\r
5736 private static final String defaultCurrencyPluralPattern = new String(defaultCurrencyPluralPatternChar);
\r
5739 // pattern used in this formatter
\r
5740 private String formatPattern = "";
\r
5741 // style is only valid when decimal formatter is constructed by
\r
5742 // DecimalFormat(pattern, decimalFormatSymbol, style)
\r
5743 private int style = NumberFormat.NUMBERSTYLE;
\r
5745 * Represents whether this is a currency format, and which
\r
5746 * currency format style.
\r
5747 * 0: not currency format type;
\r
5748 * 1: currency style -- symbol name, such as "$" for US dollar.
\r
5749 * 2: currency style -- ISO name, such as USD for US dollar.
\r
5750 * 3: currency style -- plural long name, such as "US Dollar" for
\r
5751 * "1.00 US Dollar", or "US Dollars" for
\r
5752 * "3.00 US Dollars".
\r
5754 private int currencySignCount = 0;
\r
5757 /* For parsing purose,
\r
5758 * Need to remember all prefix patterns and suffix patterns of
\r
5759 * every currency format pattern,
\r
5760 * including the pattern of default currecny style, ISO currency style,
\r
5761 * and plural currency style. And the patterns are set through applyPattern.
\r
5762 * Following are used to represent the affix patterns in currency plural
\r
5765 private static final class AffixForCurrency {
\r
5766 // negative prefix pattern
\r
5767 private String negPrefixPatternForCurrency = null;
\r
5768 // negative suffix pattern
\r
5769 private String negSuffixPatternForCurrency = null;
\r
5770 // positive prefix pattern
\r
5771 private String posPrefixPatternForCurrency = null;
\r
5772 // positive suffix pattern
\r
5773 private String posSuffixPatternForCurrency = null;
\r
5774 private int patternType;
\r
5776 public AffixForCurrency() {
\r
5777 patternType = Currency.SYMBOL_NAME;
\r
5780 public AffixForCurrency(String negPrefix, String negSuffix,
\r
5781 String posPrefix, String posSuffix,
\r
5783 negPrefixPatternForCurrency = negPrefix;
\r
5784 negSuffixPatternForCurrency = negSuffix;
\r
5785 posPrefixPatternForCurrency = posPrefix;
\r
5786 posSuffixPatternForCurrency = posSuffix;
\r
5787 patternType = type;
\r
5790 public String getNegPrefix() {
\r
5791 return negPrefixPatternForCurrency;
\r
5794 public String getNegSuffix() {
\r
5795 return negSuffixPatternForCurrency;
\r
5798 public String getPosPrefix() {
\r
5799 return posPrefixPatternForCurrency;
\r
5802 public String getPosSuffix() {
\r
5803 return posSuffixPatternForCurrency;
\r
5806 public int getPatternType() {
\r
5807 return patternType;
\r
5810 // Affix patter set for currency.
\r
5811 // It is a set of AffixForCurrency,
\r
5812 // each element of the set saves the negative prefix,
\r
5813 // negative suffix, positive prefix, and positive suffix of a pattern.
\r
5814 private transient Set affixPatternsForCurrency = null;
\r
5816 // For currency parsing, since currency parsing need to parse
\r
5817 // against all currency patterns, before the parsing, need to set up
\r
5818 // the affix patterns for currency.
\r
5819 private transient boolean isReadyForParsing = false;
\r
5821 // Information needed for DecimalFormat to format/parse currency plural.
\r
5822 private CurrencyPluralInfo currencyPluralInfo = null;
\r