]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / src / com / ibm / icu / text / DecimalFormat.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.text;\r
8 \r
9 import java.io.IOException;\r
10 import java.io.ObjectInputStream;\r
11 import java.io.ObjectOutputStream;\r
12 import java.math.BigInteger;\r
13 import java.text.AttributedCharacterIterator;\r
14 import java.text.AttributedString;\r
15 import java.text.ChoiceFormat;\r
16 import java.text.FieldPosition;\r
17 import java.text.Format;\r
18 import java.text.ParsePosition;\r
19 import java.util.ArrayList;\r
20 import java.util.HashSet;\r
21 import java.util.Iterator;\r
22 import java.util.Set;\r
23 \r
24 import com.ibm.icu.impl.ICUConfig;\r
25 import com.ibm.icu.impl.UCharacterProperty;\r
26 import com.ibm.icu.impl.Utility;\r
27 import com.ibm.icu.lang.UCharacter;\r
28 import com.ibm.icu.math.BigDecimal;\r
29 import com.ibm.icu.math.MathContext;\r
30 import com.ibm.icu.util.Currency;\r
31 import com.ibm.icu.util.CurrencyAmount;\r
32 import com.ibm.icu.util.ULocale;\r
33 \r
34 /**\r
35  * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}\r
36  *\r
37  * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats\r
38  * decimal numbers. It has a variety of features designed to make it possible to parse and\r
39  * format numbers in any locale, including support for Western, Arabic, or Indic digits.\r
40  * It also supports different flavors of numbers, including integers ("123"), fixed-point\r
41  * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency\r
42  * amounts ("$123.00", "USD123.00", "123.00 US dollars").  All of these flavors can be\r
43  * easily localized.\r
44  *\r
45  * <p>To obtain a {@link NumberFormat} for a specific locale (including the default\r
46  * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link\r
47  * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors\r
48  * directly, unless you know what you are doing, since the {@link NumberFormat} factory\r
49  * methods may return subclasses other than <code>DecimalFormat</code>. If you need to\r
50  * customize the format object, do something like this:\r
51  *\r
52  * <blockquote><pre>\r
53  * NumberFormat f = NumberFormat.getInstance(loc);\r
54  * if (f instanceof DecimalFormat) {\r
55  *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);\r
56  * }</pre></blockquote>\r
57  *\r
58  * <p><strong>Example Usage</strong>\r
59  *\r
60  * Print out a number using the localized number, currency, and percent\r
61  * format for each locale.\r
62  *\r
63  * <blockquote><pre>\r
64  * Locale[] locales = NumberFormat.getAvailableLocales();\r
65  * double myNumber = -1234.56;\r
66  * NumberFormat format;\r
67  * for (int j=0; j<3; ++j) {\r
68  *     System.out.println("FORMAT");\r
69  *     for (int i = 0; i < locales.length; ++i) {\r
70  *         if (locales[i].getCountry().length() == 0) {\r
71  *            // Skip language-only locales\r
72  *            continue;\r
73  *         }\r
74  *         System.out.print(locales[i].getDisplayName());\r
75  *         switch (j) {\r
76  *         case 0:\r
77  *             format = NumberFormat.getInstance(locales[i]); break;\r
78  *         case 1:\r
79  *             format = NumberFormat.getCurrencyInstance(locales[i]); break;\r
80  *         default:\r
81  *             format = NumberFormat.getPercentInstance(locales[i]); break;\r
82  *         }\r
83  *         try {\r
84  *             // Assume format is a DecimalFormat\r
85  *             System.out.print(": " + ((DecimalFormat) format).toPattern()\r
86  *                              + " -> " + form.format(myNumber));\r
87  *         } catch (Exception e) {}\r
88  *         try {\r
89  *             System.out.println(" -> " + format.parse(form.format(myNumber)));\r
90  *         } catch (ParseException e) {}\r
91  *     }\r
92  * }</pre></blockquote>\r
93  *\r
94  * <p>Another example use getInstance(style).<br/>\r
95  * Print out a number using the localized number, currency, percent,\r
96  * scientific, integer, iso currency, and plural currency format for each locale.\r
97  *\r
98  * <blockquote><pre>\r
99  * ULocale locale = new ULocale("en_US");\r
100  * double myNumber = 1234.56;\r
101  * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) {\r
102  *     NumberFormat format = NumberFormat.getInstance(locale, j);\r
103  *     try {\r
104  *         // Assume format is a DecimalFormat\r
105  *         System.out.print(": " + ((DecimalFormat) format).toPattern()\r
106  *                          + " -> " + form.format(myNumber));\r
107  *     } catch (Exception e) {}\r
108  *     try {\r
109  *         System.out.println(" -> " + format.parse(form.format(myNumber)));\r
110  *     } catch (ParseException e) {}\r
111  * }</pre></blockquote>\r
112  *\r
113  * <h4>Patterns</h4>\r
114  *\r
115  * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of\r
116  * <em>symbols</em>.  The pattern may be set directly using {@link #applyPattern}, or\r
117  * indirectly using other API methods which manipulate aspects of the pattern, such as the\r
118  * minimum number of integer digits.  The symbols are stored in a {@link\r
119  * DecimalFormatSymbols} object.  When using the {@link NumberFormat} factory methods, the\r
120  * pattern and symbols are read from ICU's locale data.\r
121  *\r
122  * <h4>Special Pattern Characters</h4>\r
123  *\r
124  * <p>Many characters in a pattern are taken literally; they are matched during parsing\r
125  * and output unchanged during formatting.  Special characters, on the other hand, stand\r
126  * for other characters, strings, or classes of characters.  For example, the '#'\r
127  * character is replaced by a localized digit.  Often the replacement character is the\r
128  * same as the pattern character; in the U.S. locale, the ',' grouping character is\r
129  * replaced by ','.  However, the replacement is still happening, and if the symbols are\r
130  * modified, the grouping character changes.  Some special characters affect the behavior\r
131  * of the formatter by their presence; for example, if the percent character is seen, then\r
132  * the value is multiplied by 100 before being displayed.\r
133  *\r
134  * <p>To insert a special character in a pattern as a literal, that is, without any\r
135  * special meaning, the character must be quoted.  There are some exceptions to this which\r
136  * are noted below.\r
137  *\r
138  * <p>The characters listed here are used in non-localized patterns.  Localized patterns\r
139  * use the corresponding characters taken from this formatter's {@link\r
140  * DecimalFormatSymbols} object instead, and these characters lose their special status.\r
141  * Two exceptions are the currency sign and quote, which are not localized.\r
142  *\r
143  * <blockquote>\r
144  * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,\r
145  *  location, localized, and meaning.">\r
146  *   <tr bgcolor="#ccccff">\r
147  *     <th align=left>Symbol\r
148  *     <th align=left>Location\r
149  *     <th align=left>Localized?\r
150  *     <th align=left>Meaning\r
151  *   <tr valign=top>\r
152  *     <td><code>0</code>\r
153  *     <td>Number\r
154  *     <td>Yes\r
155  *     <td>Digit\r
156  *   <tr valign=top bgcolor="#eeeeff">\r
157  *     <td><code>1-9</code>\r
158  *     <td>Number\r
159  *     <td>Yes\r
160  *     <td>'1' through '9' indicate rounding.\r
161  *   <tr valign=top>\r
162  *     <td><code>@</code>\r
163  *     <td>Number\r
164  *     <td>No\r
165  *     <td>Significant digit\r
166  *   <tr valign=top bgcolor="#eeeeff">\r
167  *     <td><code>#</code>\r
168  *     <td>Number\r
169  *     <td>Yes\r
170  *     <td>Digit, zero shows as absent\r
171  *   <tr valign=top>\r
172  *     <td><code>.</code>\r
173  *     <td>Number\r
174  *     <td>Yes\r
175  *     <td>Decimal separator or monetary decimal separator\r
176  *   <tr valign=top bgcolor="#eeeeff">\r
177  *     <td><code>-</code>\r
178  *     <td>Number\r
179  *     <td>Yes\r
180  *     <td>Minus sign\r
181  *   <tr valign=top>\r
182  *     <td><code>,</code>\r
183  *     <td>Number\r
184  *     <td>Yes\r
185  *     <td>Grouping separator\r
186  *   <tr valign=top bgcolor="#eeeeff">\r
187  *     <td><code>E</code>\r
188  *     <td>Number\r
189  *     <td>Yes\r
190  *     <td>Separates mantissa and exponent in scientific notation.\r
191  *         <em>Need not be quoted in prefix or suffix.</em>\r
192  *   <tr valign=top>\r
193  *     <td><code>+</code>\r
194  *     <td>Exponent\r
195  *     <td>Yes\r
196  *     <td>Prefix positive exponents with localized plus sign.\r
197  *         <em>Need not be quoted in prefix or suffix.</em>\r
198  *   <tr valign=top bgcolor="#eeeeff">\r
199  *     <td><code>;</code>\r
200  *     <td>Subpattern boundary\r
201  *     <td>Yes\r
202  *     <td>Separates positive and negative subpatterns\r
203  *   <tr valign=top>\r
204  *     <td><code>%</code>\r
205  *     <td>Prefix or suffix\r
206  *     <td>Yes\r
207  *     <td>Multiply by 100 and show as percentage\r
208  *   <tr valign=top bgcolor="#eeeeff">\r
209  *     <td><code>&#92;u2030</code>\r
210  *     <td>Prefix or suffix\r
211  *     <td>Yes\r
212  *     <td>Multiply by 1000 and show as per mille\r
213  *   <tr valign=top>\r
214  *     <td><code>&#164;</code> (<code>&#92;u00A4</code>)\r
215  *     <td>Prefix or suffix\r
216  *     <td>No\r
217  *     <td>Currency sign, replaced by currency symbol.  If\r
218  *         doubled, replaced by international currency symbol.\r
219  *         If tripled, replaced by currency plural names, for example,\r
220  *         "US dollar" or "US dollars" for America.\r
221  *         If present in a pattern, the monetary decimal separator\r
222  *         is used instead of the decimal separator.\r
223  *   <tr valign=top bgcolor="#eeeeff">\r
224  *     <td><code>'</code>\r
225  *     <td>Prefix or suffix\r
226  *     <td>No\r
227  *     <td>Used to quote special characters in a prefix or suffix,\r
228  *         for example, <code>"'#'#"</code> formats 123 to\r
229  *         <code>"#123"</code>.  To create a single quote\r
230  *         itself, use two in a row: <code>"# o''clock"</code>.\r
231  *   <tr valign=top>\r
232  *     <td><code>*</code>\r
233  *     <td>Prefix or suffix boundary\r
234  *     <td>Yes\r
235  *     <td>Pad escape, precedes pad character\r
236  * </table>\r
237  * </blockquote>\r
238  *\r
239  * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for\r
240  * example, "#,##0.00;(#,##0.00)".  Each subpattern has a prefix, a numeric part, and a\r
241  * suffix.  If there is no explicit negative subpattern, the negative subpattern is the\r
242  * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is\r
243  * equivalent to "0.00;-0.00".  If there is an explicit negative subpattern, it serves\r
244  * only to specify the negative prefix and suffix; the number of digits, minimal digits,\r
245  * and other characteristics are ignored in the negative subpattern. That means that\r
246  * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".\r
247  *\r
248  * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands\r
249  * separators, decimal separators, etc. may be set to arbitrary values, and they will\r
250  * appear properly during formatting.  However, care must be taken that the symbols and\r
251  * strings do not conflict, or parsing will be unreliable.  For example, either the\r
252  * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to\r
253  * be able to distinguish positive from negative values.  Another example is that the\r
254  * decimal separator and thousands separator should be distinct characters, or parsing\r
255  * will be impossible.\r
256  *\r
257  * <p>The <em>grouping separator</em> is a character that separates clusters of integer\r
258  * digits to make large numbers more legible.  It commonly used for thousands, but in some\r
259  * locales it separates ten-thousands.  The <em>grouping size</em> is the number of digits\r
260  * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000\r
261  * 0000". There are actually two different grouping sizes: One used for the least\r
262  * significant integer digits, the <em>primary grouping size</em>, and one used for all\r
263  * others, the <em>secondary grouping size</em>.  In most locales these are the same, but\r
264  * sometimes they are different. For example, if the primary grouping interval is 3, and\r
265  * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number\r
266  * 123456789 is formatted as "12,34,56,789".  If a pattern contains multiple grouping\r
267  * separators, the interval between the last one and the end of the integer defines the\r
268  * primary grouping size, and the interval between the last two defines the secondary\r
269  * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" ==\r
270  * "##,#,###,####".\r
271  *\r
272  * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause\r
273  * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message\r
274  * that describes the problem.\r
275  *\r
276  * <h4>Pattern BNF</h4>\r
277  *\r
278  * <pre>\r
279  * pattern    := subpattern (';' subpattern)?\r
280  * subpattern := prefix? number exponent? suffix?\r
281  * number     := (integer ('.' fraction)?) | sigDigits\r
282  * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters\r
283  * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters\r
284  * integer    := '#'* '0'* '0'\r
285  * fraction   := '0'* '#'*\r
286  * sigDigits  := '#'* '@' '@'* '#'*\r
287  * exponent   := 'E' '+'? '0'* '0'\r
288  * padSpec    := '*' padChar\r
289  * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote\r
290  * &#32;\r
291  * Notation:\r
292  *   X*       0 or more instances of X\r
293  *   X?       0 or 1 instances of X\r
294  *   X|Y      either X or Y\r
295  *   C..D     any character from C up to D, inclusive\r
296  *   S-T      characters in S, except those in T\r
297  * </pre>\r
298  * The first subpattern is for positive numbers. The second (optional)\r
299  * subpattern is for negative numbers.\r
300  *\r
301  * <p>Not indicated in the BNF syntax above:\r
302  *\r
303  * <ul>\r
304  *\r
305  * <li>The grouping separator ',' can occur inside the integer and sigDigits\r
306  * elements, between any two pattern characters of that element, as long as the integer or\r
307  * sigDigits element is not followed by the exponent element.\r
308  *\r
309  * <li>Two grouping intervals are recognized: That between the decimal point and the first\r
310  * grouping symbol, and that between the first and second grouping symbols. These\r
311  * intervals are identical in most locales, but in some locales they differ. For example,\r
312  * the pattern &quot;#,##,###&quot; formats the number 123456789 as\r
313  * &quot;12,34,56,789&quot;.\r
314  *\r
315  * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the\r
316  * prefix, before the suffix, after the suffix, or not at all.\r
317  *\r
318  * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding\r
319  * increment.\r
320  *\r
321  * </ul>\r
322  *\r
323  * <h4>Parsing</h4>\r
324  *\r
325  * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal\r
326  * digits, as defined by {@link UCharacter#digit}.  In addition,\r
327  * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters\r
328  * starting with the localized zero digit defined in the {@link DecimalFormatSymbols}\r
329  * object.  During formatting, the {@link DecimalFormatSymbols}-based digits are output.\r
330  *\r
331  * <p>During parsing, grouping separators are ignored.\r
332  *\r
333  * <p>For currency parsing, the formatter is able to parse every currency style formats no\r
334  * matter which style the formatter is constructed with.  For example, a formatter\r
335  * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can\r
336  * parse formats such as "USD1.00" and "3.00 US dollars".\r
337  *\r
338  * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns\r
339  * <code>null</code> and leaves the parse position unchanged.  The convenience method\r
340  * {@link #parse(String)} indicates parse failure by throwing a {@link\r
341  * java.text.ParseException}.\r
342  *\r
343  * <h4>Formatting</h4>\r
344  *\r
345  * <p>Formatting is guided by several parameters, all of which can be specified either\r
346  * using a pattern or using the API.  The following description applies to formats that do\r
347  * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant\r
348  * digits</a>.\r
349  *\r
350  * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer\r
351  * digits</em>, then only the least significant digits are shown.  For example, 1997 is\r
352  * formatted as "97" if the maximum integer digits is set to 2.\r
353  *\r
354  * <li>If the number of actual integer digits is less than the <em>minimum integer\r
355  * digits</em>, then leading zeros are added.  For example, 1997 is formatted as "01997"\r
356  * if the minimum integer digits is set to 5.\r
357  *\r
358  * <li>If the number of actual fraction digits exceeds the <em>maximum fraction\r
359  * digits</em>, then half-even rounding it performed to the maximum fraction digits.  For\r
360  * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2.  This\r
361  * behavior can be changed by specifying a rounding increment and a rounding mode.\r
362  *\r
363  * <li>If the number of actual fraction digits is less than the <em>minimum fraction\r
364  * digits</em>, then trailing zeros are added.  For example, 0.125 is formatted as\r
365  * "0.1250" if the mimimum fraction digits is set to 4.\r
366  *\r
367  * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions\r
368  * after the decimal, where <em>j</em> is less than the maximum fraction digits. For\r
369  * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less.\r
370  * </ul>\r
371  *\r
372  * <p><strong>Special Values</strong>\r
373  *\r
374  * <p><code>NaN</code> is represented as a single character, typically\r
375  * <code>&#92;uFFFD</code>.  This character is determined by the {@link\r
376  * DecimalFormatSymbols} object.  This is the only value for which the prefixes and\r
377  * suffixes are not used.\r
378  *\r
379  * <p>Infinity is represented as a single character, typically <code>&#92;u221E</code>,\r
380  * with the positive or negative prefixes and suffixes applied.  The infinity character is\r
381  * determined by the {@link DecimalFormatSymbols} object.\r
382  *\r
383  * <a name="sci"><h4>Scientific Notation</h4></a>\r
384  *\r
385  * <p>Numbers in scientific notation are expressed as the product of a mantissa and a\r
386  * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The\r
387  * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0),\r
388  * but it need not be.  <code>DecimalFormat</code> supports arbitrary mantissas.\r
389  * <code>DecimalFormat</code> can be instructed to use scientific notation through the API\r
390  * or through the pattern.  In a pattern, the exponent character immediately followed by\r
391  * one or more digit characters indicates scientific notation.  Example: "0.###E0" formats\r
392  * the number 1234 as "1.234E3".\r
393  *\r
394  * <ul>\r
395  *\r
396  * <li>The number of digit characters after the exponent character gives the minimum\r
397  * exponent digit count.  There is no maximum.  Negative exponents are formatted using the\r
398  * localized minus sign, <em>not</em> the prefix and suffix from the pattern.  This allows\r
399  * patterns such as "0.###E0 m/s".  To prefix positive exponents with a localized plus\r
400  * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats\r
401  * "1E+1", "1E+0", "1E-1", etc.  (In localized patterns, use the localized plus sign\r
402  * rather than '+'.)\r
403  *\r
404  * <li>The minimum number of integer digits is achieved by adjusting the exponent.\r
405  * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".  This only happens if\r
406  * there is no maximum number of integer digits.  If there is a maximum, then the minimum\r
407  * number of integer digits is fixed at one.\r
408  *\r
409  * <li>The maximum number of integer digits, if present, specifies the exponent grouping.\r
410  * The most common use of this is to generate <em>engineering notation</em>, in which the\r
411  * exponent is a multiple of three, e.g., "##0.###E0".  The number 12345 is formatted\r
412  * using "##0.####E0" as "12.345E3".\r
413  *\r
414  * <li>When using scientific notation, the formatter controls the digit counts using\r
415  * significant digits logic.  The maximum number of significant digits limits the total\r
416  * number of integer and fraction digits that will be shown in the mantissa; it does not\r
417  * affect parsing.  For example, 12345 formatted with "##0.##E0" is "12.3E3".  See the\r
418  * section on significant digits for more details.\r
419  *\r
420  * <li>The number of significant digits shown is determined as follows: If\r
421  * areSignificantDigitsUsed() returns false, then the minimum number of significant digits\r
422  * shown is one, and the maximum number of significant digits shown is the sum of the\r
423  * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the\r
424  * maximum integer digits.  If this sum is zero, then all significant digits are shown.\r
425  * If areSignificantDigitsUsed() returns true, then the significant digit counts are\r
426  * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits().  In this\r
427  * case, the number of integer digits is fixed at one, and there is no exponent grouping.\r
428  *\r
429  * <li>Exponential patterns may not contain grouping separators.\r
430  *\r
431  * </ul>\r
432  *\r
433  * <a name="sigdig"><h4>Significant Digits</h4></a>\r
434  *\r
435  * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a)\r
436  * significant digits counts, or (b) integer and fraction digit counts.  Integer and\r
437  * fraction digit counts are described above.  When a formatter is using significant\r
438  * digits counts, the number of integer and fraction digits is not specified directly, and\r
439  * the formatter settings for these counts are ignored.  Instead, the formatter uses\r
440  * however many integer and fraction digits are required to display the specified number\r
441  * of significant digits.  Examples:\r
442  *\r
443  * <blockquote>\r
444  * <table border=0 cellspacing=3 cellpadding=0>\r
445  *   <tr bgcolor="#ccccff">\r
446  *     <th align=left>Pattern\r
447  *     <th align=left>Minimum significant digits\r
448  *     <th align=left>Maximum significant digits\r
449  *     <th align=left>Number\r
450  *     <th align=left>Output of format()\r
451  *   <tr valign=top>\r
452  *     <td><code>@@@</code>\r
453  *     <td>3\r
454  *     <td>3\r
455  *     <td>12345\r
456  *     <td><code>12300</code>\r
457  *   <tr valign=top bgcolor="#eeeeff">\r
458  *     <td><code>@@@</code>\r
459  *     <td>3\r
460  *     <td>3\r
461  *     <td>0.12345\r
462  *     <td><code>0.123</code>\r
463  *   <tr valign=top>\r
464  *     <td><code>@@##</code>\r
465  *     <td>2\r
466  *     <td>4\r
467  *     <td>3.14159\r
468  *     <td><code>3.142</code>\r
469  *   <tr valign=top bgcolor="#eeeeff">\r
470  *     <td><code>@@##</code>\r
471  *     <td>2\r
472  *     <td>4\r
473  *     <td>1.23004\r
474  *     <td><code>1.23</code>\r
475  * </table>\r
476  * </blockquote>\r
477  *\r
478  * <ul>\r
479  *\r
480  * <li>Significant digit counts may be expressed using patterns that specify a minimum and\r
481  * maximum number of significant digits.  These are indicated by the <code>'@'</code> and\r
482  * <code>'#'</code> characters.  The minimum number of significant digits is the number of\r
483  * <code>'@'</code> characters.  The maximum number of significant digits is the number of\r
484  * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on\r
485  * the right.  For example, the pattern <code>"@@@"</code> indicates exactly 3 significant\r
486  * digits.  The pattern <code>"@##"</code> indicates from 1 to 3 significant digits.\r
487  * Trailing zero digits to the right of the decimal separator are suppressed after the\r
488  * minimum number of significant digits have been shown.  For example, the pattern\r
489  * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>.\r
490  *\r
491  * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor\r
492  * the <code>'0'</code> pattern character.  Patterns such as <code>"@00"</code> or\r
493  * <code>"@.###"</code> are disallowed.\r
494  *\r
495  * <li>Any number of <code>'#'</code> characters may be prepended to the left of the\r
496  * leftmost <code>'@'</code> character.  These have no effect on the minimum and maximum\r
497  * significant digits counts, but may be used to position grouping separators.  For\r
498  * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum\r
499  * of two significant digits, and a grouping size of three.\r
500  *\r
501  * <li>In order to enable significant digits formatting, use a pattern containing the\r
502  * <code>'@'</code> pattern character.  Alternatively, call {@link\r
503  * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}.\r
504  *\r
505  * <li>In order to disable significant digits formatting, use a pattern that does not\r
506  * contain the <code>'@'</code> pattern character. Alternatively, call {@link\r
507  * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}.\r
508  *\r
509  * <li>The number of significant digits has no effect on parsing.\r
510  *\r
511  * <li>Significant digits may be used together with exponential notation. Such patterns\r
512  * are equivalent to a normal exponential pattern with a minimum and maximum integer digit\r
513  * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() -\r
514  * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() -\r
515  * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to\r
516  * <code>"0.0###E0"</code>.\r
517  *\r
518  * <li>If signficant digits are in use, then the integer and fraction digit counts, as set\r
519  * via the API, are ignored.  If significant digits are not in use, then the signficant\r
520  * digit counts, as set via the API, are ignored.\r
521  *\r
522  * </ul>\r
523  *\r
524  * <h4>Padding</h4>\r
525  *\r
526  * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a\r
527  * specific width.  Padding may be specified either through the API or through the pattern\r
528  * syntax.  In a pattern the pad escape character, followed by a single pad character,\r
529  * causes padding to be parsed and formatted.  The pad escape character is '*' in\r
530  * unlocalized patterns, and can be localized using {@link\r
531  * DecimalFormatSymbols#setPadEscape}.  For example, <code>"$*x#,##0.00"</code> formats\r
532  * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>.\r
533  *\r
534  * <ul>\r
535  *\r
536  * <li>When padding is in effect, the width of the positive subpattern, including prefix\r
537  * and suffix, determines the format width.  For example, in the pattern <code>"* #0\r
538  * o''clock"</code>, the format width is 10.\r
539  *\r
540  * <li>The width is counted in 16-bit code units (Java <code>char</code>s).\r
541  *\r
542  * <li>Some parameters which usually do not matter have meaning when padding is used,\r
543  * because the pattern width is significant with padding.  In the pattern "*\r
544  * ##,##,#,##0.##", the format width is 14.  The initial characters "##,##," do not affect\r
545  * the grouping size or maximum integer digits, but they do affect the format width.\r
546  *\r
547  * <li>Padding may be inserted at one of four locations: before the prefix, after the\r
548  * prefix, before the suffix, or after the suffix.  If padding is specified in any other\r
549  * location, {@link #applyPattern} throws an {@link IllegalArgumentException}.  If there\r
550  * is no prefix, before the prefix and after the prefix are equivalent, likewise for the\r
551  * suffix.\r
552  *\r
553  * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the\r
554  * pad escape is the pad character. This may be any character, including a special pattern\r
555  * character. That is, the pad escape <em>escapes</em> the following character. If there\r
556  * is no character after the pad escape, then the pattern is illegal.\r
557  *\r
558  * </ul>\r
559  *\r
560  * <p>\r
561  * <strong>Rounding</strong>\r
562  *\r
563  * <p><code>DecimalFormat</code> supports rounding to a specific increment.  For example,\r
564  * 1230 rounded to the nearest 50 is 1250.  1.234 rounded to the nearest 0.65 is 1.3.  The\r
565  * rounding increment may be specified through the API or in a pattern.  To specify a\r
566  * rounding increment in a pattern, include the increment in the pattern itself.  "#,#50"\r
567  * specifies a rounding increment of 50.  "#,##0.05" specifies a rounding increment of\r
568  * 0.05.\r
569  *\r
570  * <ul>\r
571  *\r
572  * <li>Rounding only affects the string produced by formatting.  It does not affect\r
573  * parsing or change any numerical values.\r
574  *\r
575  * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link\r
576  * com.ibm.icu.math.BigDecimal} documentation for a description of the modes.  Rounding\r
577  * increments specified in patterns use the default mode, {@link\r
578  * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}.\r
579  *\r
580  * <li>Some locales use rounding in their currency formats to reflect the smallest\r
581  * currency denomination.\r
582  *\r
583  * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave\r
584  * identically to digit '0'.\r
585  *\r
586  * </ul>\r
587  *\r
588  * <h4>Synchronization</h4>\r
589  *\r
590  * <p><code>DecimalFormat</code> objects are not synchronized.  Multiple threads should\r
591  * not access one formatter concurrently.\r
592  *\r
593  * @see          java.text.Format\r
594  * @see          NumberFormat\r
595  * @author       Mark Davis\r
596  * @author       Alan Liu\r
597  * @stable ICU 2.0\r
598  */\r
599 public class DecimalFormat extends NumberFormat {\r
600 \r
601     /**\r
602      * Creates a DecimalFormat using the default pattern and symbols for the default\r
603      * locale. This is a convenient way to obtain a DecimalFormat when\r
604      * internationalization is not the main concern.\r
605      *\r
606      * <p>To obtain standard formats for a given locale, use the factory methods on\r
607      * NumberFormat such as getNumberInstance.  These factories will return the most\r
608      * appropriate sub-class of NumberFormat for a given locale.\r
609      *\r
610      * @see NumberFormat#getInstance\r
611      * @see NumberFormat#getNumberInstance\r
612      * @see NumberFormat#getCurrencyInstance\r
613      * @see NumberFormat#getPercentInstance\r
614      * @stable ICU 2.0\r
615      */\r
616     public DecimalFormat() {\r
617         ULocale def = ULocale.getDefault();\r
618         String pattern = getPattern(def, 0);\r
619         // Always applyPattern after the symbols are set\r
620         this.symbols = new DecimalFormatSymbols(def);\r
621         setCurrency(Currency.getInstance(def));\r
622         applyPatternWithoutExpandAffix(pattern, false);\r
623         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {\r
624             currencyPluralInfo = new CurrencyPluralInfo(def);\r
625             // the exact pattern is not known until the plural count is known.\r
626             // so, no need to expand affix now.\r
627         } else {\r
628             expandAffixAdjustWidth(null);\r
629         }\r
630     }\r
631 \r
632     /**\r
633      * Creates a DecimalFormat from the given pattern and the symbols for the default\r
634      * locale. This is a convenient way to obtain a DecimalFormat when\r
635      * internationalization is not the main concern.\r
636      *\r
637      * <p>To obtain standard formats for a given locale, use the factory methods on\r
638      * NumberFormat such as getNumberInstance.  These factories will return the most\r
639      * appropriate sub-class of NumberFormat for a given locale.\r
640      *\r
641      * @param pattern A non-localized pattern string.\r
642      * @throws IllegalArgumentException if the given pattern is invalid.\r
643      * @see NumberFormat#getInstance\r
644      * @see NumberFormat#getNumberInstance\r
645      * @see NumberFormat#getCurrencyInstance\r
646      * @see NumberFormat#getPercentInstance\r
647      * @stable ICU 2.0\r
648      */\r
649     public DecimalFormat(String pattern) {\r
650         // Always applyPattern after the symbols are set\r
651         ULocale def = ULocale.getDefault();\r
652         this.symbols = new DecimalFormatSymbols(def);\r
653         setCurrency(Currency.getInstance(def));\r
654         applyPatternWithoutExpandAffix(pattern, false);\r
655         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {\r
656             currencyPluralInfo = new CurrencyPluralInfo(def);\r
657         } else {\r
658             expandAffixAdjustWidth(null);\r
659         }\r
660     }\r
661 \r
662     /**\r
663      * Creates a DecimalFormat from the given pattern and symbols. Use this constructor\r
664      * when you need to completely customize the behavior of the format.\r
665      *\r
666      * <p>To obtain standard formats for a given locale, use the factory methods on\r
667      * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor\r
668      * adjustments to a standard format, you can modify the format returned by a\r
669      * NumberFormat factory method.\r
670      *\r
671      * @param pattern a non-localized pattern string\r
672      * @param symbols the set of symbols to be used\r
673      * @exception IllegalArgumentException if the given pattern is invalid\r
674      * @see NumberFormat#getInstance\r
675      * @see NumberFormat#getNumberInstance\r
676      * @see NumberFormat#getCurrencyInstance\r
677      * @see NumberFormat#getPercentInstance\r
678      * @see DecimalFormatSymbols\r
679      * @stable ICU 2.0\r
680      */\r
681     public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {\r
682         createFromPatternAndSymbols(pattern, symbols);\r
683     }\r
684 \r
685     private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) {\r
686         // Always applyPattern after the symbols are set\r
687         symbols = (DecimalFormatSymbols) inputSymbols.clone();\r
688         setCurrencyForSymbols();\r
689         applyPatternWithoutExpandAffix(pattern, false);\r
690         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {\r
691             currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());\r
692         } else {\r
693             expandAffixAdjustWidth(null);\r
694         }\r
695     }\r
696 \r
697     /**\r
698      * Creates a DecimalFormat from the given pattern, symbols, information used for\r
699      * currency plural format, and format style. Use this constructor when you need to\r
700      * completely customize the behavior of the format.\r
701      *\r
702      * <p>To obtain standard formats for a given locale, use the factory methods on\r
703      * NumberFormat such as getInstance or getCurrencyInstance.\r
704      *\r
705      * <p>If you need only minor adjustments to a standard format, you can modify the\r
706      * format returned by a NumberFormat factory method using the setters.\r
707      *\r
708      * <p>If you want to completely customize a decimal format, using your own\r
709      * DecimalFormatSymbols (such as group separators) and your own information for\r
710      * currency plural formatting (such as plural rule and currency plural patterns), you\r
711      * can use this constructor.\r
712      *\r
713      * @param pattern a non-localized pattern string\r
714      * @param symbols the set of symbols to be used\r
715      * @param infoInput the information used for currency plural format, including\r
716      * currency plural patterns and plural rules.\r
717      * @param style the decimal formatting style, it is one of the following values:\r
718      * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;\r
719      * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE;\r
720      * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE;\r
721      * @stable ICU 4.2\r
722      */\r
723     public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput,\r
724                          int style) {\r
725         CurrencyPluralInfo info = infoInput;\r
726         if (style == NumberFormat.PLURALCURRENCYSTYLE) {\r
727             info = (CurrencyPluralInfo) infoInput.clone();\r
728         }\r
729         create(pattern, symbols, info, style);\r
730     }\r
731 \r
732     private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info,\r
733                         int inputStyle) {\r
734         if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) {\r
735             createFromPatternAndSymbols(pattern, inputSymbols);\r
736         } else {\r
737             // Always applyPattern after the symbols are set\r
738             symbols = (DecimalFormatSymbols) inputSymbols.clone();\r
739             currencyPluralInfo = info;\r
740             // the pattern used in format is not fixed until formatting, in which, the\r
741             // number is known and will be used to pick the right pattern based on plural\r
742             // count.  Here, set the pattern as the pattern of plural count == "other".\r
743             // For most locale, the patterns are probably the same for all plural\r
744             // count. If not, the right pattern need to be re-applied during format.\r
745             String currencyPluralPatternForOther =\r
746                 currencyPluralInfo.getCurrencyPluralPattern("other");\r
747             applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false);\r
748             setCurrencyForSymbols();\r
749         }\r
750         style = inputStyle;\r
751     }\r
752 \r
753     /**\r
754      * Creates a DecimalFormat for currency plural format from the given pattern, symbols,\r
755      * and style.\r
756      */\r
757     DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) {\r
758         CurrencyPluralInfo info = null;\r
759         if (style == NumberFormat.PLURALCURRENCYSTYLE) {\r
760             info = new CurrencyPluralInfo(inputSymbols.getLocale());\r
761         }\r
762         create(pattern, inputSymbols, info, style);\r
763     }\r
764 \r
765     /**\r
766      * {@inheritDoc}\r
767      * @stable ICU 2.0\r
768      */\r
769     public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {\r
770         return format(number, result, fieldPosition, false);\r
771     }\r
772 \r
773     // [Spark/CDL] The actual method to format number. If boolean value\r
774     // parseAttr == true, then attribute information will be recorded.\r
775     private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition,\r
776                                 boolean parseAttr) {\r
777         fieldPosition.setBeginIndex(0);\r
778         fieldPosition.setEndIndex(0);\r
779 \r
780         if (Double.isNaN(number)) {\r
781             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
782                 fieldPosition.setBeginIndex(result.length());\r
783             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
784                 fieldPosition.setBeginIndex(result.length());\r
785             }\r
786 \r
787             result.append(symbols.getNaN());\r
788             // [Spark/CDL] Add attribute for NaN here.\r
789             // result.append(symbols.getNaN());\r
790             if (parseAttr) {\r
791                 addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(),\r
792                              result.length());\r
793             }\r
794             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
795                 fieldPosition.setEndIndex(result.length());\r
796             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
797                 fieldPosition.setEndIndex(result.length());\r
798             }\r
799 \r
800             addPadding(result, fieldPosition, 0, 0);\r
801             return result;\r
802         }\r
803 \r
804         // Do this BEFORE checking to see if value is infinite or negative!\r
805         if (multiplier != 1)\r
806             number *= multiplier;\r
807 \r
808 \r
809         // Detecting whether a double is negative is easy with the exception of the value\r
810         // -0.0. This is a double which has a zero mantissa (and exponent), but a negative\r
811         // sign bit. It is semantically distinct from a zero with a positive sign bit, and\r
812         // this distinction is important to certain kinds of computations. However, it's a\r
813         // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you\r
814         // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==\r
815         // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by\r
816         // bugs 4106658, 4106667, and 4147706. Liu 7/6/98.\r
817         boolean isNegative = (number < 0.0) || (number == 0.0 && 1 / number < 0.0);\r
818         if (isNegative)\r
819             number = -number;\r
820 \r
821         // Apply rounding after multiplier\r
822         if (roundingDouble > 0.0) {\r
823             // number = roundingDouble\r
824             //    * round(number / roundingDouble, roundingMode, isNegative);\r
825             double newNumber = round(number, roundingDouble, roundingDoubleReciprocal, roundingMode,\r
826                                      isNegative);\r
827             if (newNumber == 0.0 && number != newNumber)\r
828                 isNegative = false; // if we touched it, then make zero be zero.\r
829             number = newNumber;\r
830         }\r
831 \r
832         if (Double.isInfinite(number)) {\r
833             int prefixLen = appendAffix(result, isNegative, true, parseAttr);\r
834 \r
835             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
836                 fieldPosition.setBeginIndex(result.length());\r
837             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
838                 fieldPosition.setBeginIndex(result.length());\r
839             }\r
840 \r
841             // [Spark/CDL] Add attribute for infinity here.\r
842             result.append(symbols.getInfinity());\r
843             if (parseAttr) {\r
844                 addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(),\r
845                              result.length());\r
846             }\r
847             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
848                 fieldPosition.setEndIndex(result.length());\r
849             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
850                 fieldPosition.setEndIndex(result.length());\r
851             }\r
852 \r
853             int suffixLen = appendAffix(result, isNegative, false, parseAttr);\r
854 \r
855             addPadding(result, fieldPosition, prefixLen, suffixLen);\r
856             return result;\r
857         }\r
858 \r
859         // At this point we are guaranteed a nonnegative finite\r
860         // number.\r
861         synchronized (digitList) {\r
862             digitList.set(number, precision(false), !useExponentialNotation &&\r
863                           !areSignificantDigitsUsed());\r
864             return subformat(number, result, fieldPosition, isNegative, false, parseAttr);\r
865         }\r
866     }\r
867 \r
868     /**\r
869      * Round a double value to the nearest multiple of the given rounding increment,\r
870      * according to the given mode. This is equivalent to rounding value/roundingInc to\r
871      * the nearest integer, according to the given mode, and returning that integer *\r
872      * roundingInc. Note this is changed from the version in 2.4, since division of\r
873      * doubles have inaccuracies. jitterbug 1871.\r
874      *\r
875      * @param number\r
876      *            the absolute value of the number to be rounded\r
877      * @param roundingInc\r
878      *            the rounding increment\r
879      * @param roundingIncReciprocal\r
880      *            if non-zero, is the\r
881      * @param mode\r
882      *            a BigDecimal rounding mode\r
883      * @param isNegative\r
884      *            true if the number to be rounded is negative\r
885      * @return the absolute value of the rounded result\r
886      */\r
887     private static double round(double number, double roundingInc, double roundingIncReciprocal,\r
888                                 int mode, boolean isNegative) {\r
889 \r
890         double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number *\r
891             roundingIncReciprocal;\r
892 \r
893         // do the absolute cases first\r
894 \r
895         switch (mode) {\r
896         case BigDecimal.ROUND_CEILING:\r
897             div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon));\r
898             break;\r
899         case BigDecimal.ROUND_FLOOR:\r
900             div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon));\r
901             break;\r
902         case BigDecimal.ROUND_DOWN:\r
903             div = (Math.floor(div + epsilon));\r
904             break;\r
905         case BigDecimal.ROUND_UP:\r
906             div = (Math.ceil(div - epsilon));\r
907             break;\r
908         case BigDecimal.ROUND_UNNECESSARY:\r
909             if (div != Math.floor(div)) {\r
910                 throw new ArithmeticException("Rounding necessary");\r
911             }\r
912             return number;\r
913         default:\r
914 \r
915             // Handle complex cases, where the choice depends on the closer value.\r
916 \r
917             // We figure out the distances to the two possible values, ceiling and floor.\r
918             // We then go for the diff that is smaller.  Only if they are equal does the\r
919             // mode matter.\r
920 \r
921             double ceil = Math.ceil(div);\r
922             double ceildiff = ceil - div; // (ceil * roundingInc) - number;\r
923             double floor = Math.floor(div);\r
924             double floordiff = div - floor; // number - (floor * roundingInc);\r
925 \r
926             // Note that the diff values were those mapped back to the "normal" space by\r
927             // using the roundingInc. I don't have access to the original author of the\r
928             // code but suspect that that was to produce better result in edge cases\r
929             // because of machine precision, rather than simply using the difference\r
930             // between, say, ceil and div.  However, it didn't work in all cases. Am\r
931             // trying instead using an epsilon value.\r
932 \r
933             switch (mode) {\r
934             case BigDecimal.ROUND_HALF_EVEN:\r
935                 // We should be able to just return Math.rint(a), but this\r
936                 // doesn't work in some VMs.\r
937                 // if one is smaller than the other, take the corresponding side\r
938                 if (floordiff + epsilon < ceildiff) {\r
939                     div = floor;\r
940                 } else if (ceildiff + epsilon < floordiff) {\r
941                     div = ceil;\r
942                 } else { // they are equal, so we want to round to whichever is even\r
943                     double testFloor = floor / 2;\r
944                     div = (testFloor == Math.floor(testFloor)) ? floor : ceil;\r
945                 }\r
946                 break;\r
947             case BigDecimal.ROUND_HALF_DOWN:\r
948                 div = ((floordiff <= ceildiff + epsilon) ? floor : ceil);\r
949                 break;\r
950             case BigDecimal.ROUND_HALF_UP:\r
951                 div = ((ceildiff <= floordiff + epsilon) ? ceil : floor);\r
952                 break;\r
953             default:\r
954                 throw new IllegalArgumentException("Invalid rounding mode: " + mode);\r
955             }\r
956         }\r
957         number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal;\r
958         return number;\r
959     }\r
960 \r
961     private static double epsilon = 0.00000000001;\r
962 \r
963     /**\r
964      * @stable ICU 2.0\r
965      */\r
966     // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean\r
967     public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {\r
968         return format(number, result, fieldPosition, false);\r
969     }\r
970 \r
971     private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition,\r
972                                 boolean parseAttr) {\r
973         fieldPosition.setBeginIndex(0);\r
974         fieldPosition.setEndIndex(0);\r
975 \r
976         // If we are to do rounding, we need to move into the BigDecimal\r
977         // domain in order to do divide/multiply correctly.\r
978         if (roundingIncrementICU != null) {\r
979             return format(BigDecimal.valueOf(number), result, fieldPosition);\r
980         }\r
981 \r
982         boolean isNegative = (number < 0);\r
983         if (isNegative)\r
984             number = -number;\r
985 \r
986         // In general, long values always represent real finite numbers, so we don't have\r
987         // to check for +/- Infinity or NaN. However, there is one case we have to be\r
988         // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE\r
989         // outside the legal range. We check for this before multiplying, and if it\r
990         // happens we use BigInteger instead.\r
991         if (multiplier != 1) {\r
992             boolean tooBig = false;\r
993             if (number < 0) { // This can only happen if number == Long.MIN_VALUE\r
994                 long cutoff = Long.MIN_VALUE / multiplier;\r
995                 tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1\r
996             } else {\r
997                 long cutoff = Long.MAX_VALUE / multiplier;\r
998                 tooBig = (number > cutoff);\r
999             }\r
1000             if (tooBig) {\r
1001                 // [Spark/CDL] Use\r
1002                 // format_BigInteger_StringBuffer_FieldPosition_boolean instead\r
1003                 // parseAttr is used to judge whether to synthesize attributes.\r
1004                 return format(BigInteger.valueOf(isNegative ? -number : number), result,\r
1005                               fieldPosition, parseAttr);\r
1006             }\r
1007         }\r
1008 \r
1009         number *= multiplier;\r
1010         synchronized (digitList) {\r
1011             digitList.set(number, precision(true));\r
1012             return subformat(number, result, fieldPosition, isNegative, true, parseAttr);\r
1013         }\r
1014     }\r
1015 \r
1016     /**\r
1017      * Formats a BigInteger number.\r
1018      *\r
1019      * @stable ICU 2.0\r
1020      */\r
1021     public StringBuffer format(BigInteger number, StringBuffer result,\r
1022                                FieldPosition fieldPosition) {\r
1023         return format(number, result, fieldPosition, false);\r
1024     }\r
1025 \r
1026     private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition,\r
1027                                 boolean parseAttr) {\r
1028         // If we are to do rounding, we need to move into the BigDecimal\r
1029         // domain in order to do divide/multiply correctly.\r
1030         if (roundingIncrementICU != null) {\r
1031             return format(new BigDecimal(number), result, fieldPosition);\r
1032         }\r
1033 \r
1034         if (multiplier != 1) {\r
1035             number = number.multiply(BigInteger.valueOf(multiplier));\r
1036         }\r
1037 \r
1038         // At this point we are guaranteed a nonnegative finite\r
1039         // number.\r
1040         synchronized (digitList) {\r
1041             digitList.set(number, precision(true));\r
1042             return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,\r
1043                              parseAttr);\r
1044         }\r
1045     }\r
1046 \r
1047     /**\r
1048      * Formats a BigDecimal number.\r
1049      *\r
1050      * @stable ICU 2.0\r
1051      */\r
1052     public StringBuffer format(java.math.BigDecimal number, StringBuffer result,\r
1053                                FieldPosition fieldPosition) {\r
1054         return format(number, result, fieldPosition, false);\r
1055     }\r
1056 \r
1057     private StringBuffer format(java.math.BigDecimal number, StringBuffer result,\r
1058                                 FieldPosition fieldPosition,\r
1059             boolean parseAttr) {\r
1060         if (multiplier != 1) {\r
1061             number = number.multiply(java.math.BigDecimal.valueOf(multiplier));\r
1062         }\r
1063 \r
1064         if (roundingIncrement != null) {\r
1065             number = number.divide(roundingIncrement, 0, roundingMode).multiply(roundingIncrement);\r
1066         }\r
1067 \r
1068         synchronized (digitList) {\r
1069             digitList.set(number, precision(false), !useExponentialNotation &&\r
1070                           !areSignificantDigitsUsed());\r
1071             return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,\r
1072                              false, parseAttr);\r
1073         }\r
1074     }\r
1075 \r
1076     /**\r
1077      * Formats a BigDecimal number.\r
1078      *\r
1079      * @stable ICU 2.0\r
1080      */\r
1081     public StringBuffer format(BigDecimal number, StringBuffer result,\r
1082                                FieldPosition fieldPosition) {\r
1083          // This method is just a copy of the corresponding java.math.BigDecimal method\r
1084          // for now. It isn't very efficient since it must create a conversion object to\r
1085          // do math on the rounding increment. In the future we may try to clean this up,\r
1086          // or even better, limit our support to just one flavor of BigDecimal.\r
1087         if (multiplier != 1) {\r
1088             number = number.multiply(BigDecimal.valueOf(multiplier), mathContext);\r
1089         }\r
1090 \r
1091         if (roundingIncrementICU != null) {\r
1092             number = number.divide(roundingIncrementICU, 0, roundingMode)\r
1093                 .multiply(roundingIncrementICU, mathContext);\r
1094         }\r
1095 \r
1096         synchronized (digitList) {\r
1097             digitList.set(number, precision(false), !useExponentialNotation &&\r
1098                           !areSignificantDigitsUsed());\r
1099             return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,\r
1100                              false, false);\r
1101         }\r
1102     }\r
1103 \r
1104     /**\r
1105      * Returns true if a grouping separator belongs at the given position, based on whether\r
1106      * grouping is in use and the values of the primary and secondary grouping interval.\r
1107      *\r
1108      * @param pos the number of integer digits to the right of the current position. Zero\r
1109      * indicates the position after the rightmost integer digit.\r
1110      * @return true if a grouping character belongs at the current position.\r
1111      */\r
1112     private boolean isGroupingPosition(int pos) {\r
1113         boolean result = false;\r
1114         if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) {\r
1115             if ((groupingSize2 > 0) && (pos > groupingSize)) {\r
1116                 result = ((pos - groupingSize) % groupingSize2) == 0;\r
1117             } else {\r
1118                 result = pos % groupingSize == 0;\r
1119             }\r
1120         }\r
1121         return result;\r
1122     }\r
1123 \r
1124     /**\r
1125      * Return the number of fraction digits to display, or the total\r
1126      * number of digits for significant digit formats and exponential\r
1127      * formats.\r
1128      */\r
1129     private int precision(boolean isIntegral) {\r
1130         if (areSignificantDigitsUsed()) {\r
1131             return getMaximumSignificantDigits();\r
1132         } else if (useExponentialNotation) {\r
1133             return getMinimumIntegerDigits() + getMaximumFractionDigits();\r
1134         } else {\r
1135             return isIntegral ? 0 : getMaximumFractionDigits();\r
1136         }\r
1137     }\r
1138 \r
1139     private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition,\r
1140                                    boolean isNegative, boolean isInteger, boolean parseAttr) {\r
1141         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {\r
1142             return subformat(currencyPluralInfo.select(number), result, fieldPosition, isNegative,\r
1143                              isInteger, parseAttr);\r
1144         } else {\r
1145             return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);\r
1146         }\r
1147     }\r
1148 \r
1149     private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition,\r
1150                                    boolean isNegative,\r
1151             boolean isInteger, boolean parseAttr) {\r
1152         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {\r
1153             return subformat(currencyPluralInfo.select(number), result, fieldPosition, isNegative,\r
1154                              isInteger, parseAttr);\r
1155         } else {\r
1156             return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);\r
1157         }\r
1158     }\r
1159 \r
1160     private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition,\r
1161             boolean isNegative, boolean isInteger, boolean parseAttr) {\r
1162         // There are 2 ways to activate currency plural format: by applying a pattern with\r
1163         // 3 currency sign directly, or by instantiate a decimal formatter using\r
1164         // PLURALCURRENCYSTYLE.  For both cases, the number of currency sign in the\r
1165         // pattern is 3.  Even if the number of currency sign in the pattern is 3, it does\r
1166         // not mean we need to reset the pattern.  For 1st case, we do not need to reset\r
1167         // pattern.  For 2nd case, we might need to reset pattern, if the default pattern\r
1168         // (corresponding to plural count 'other') we use is different from the pattern\r
1169         // based on 'pluralCount'.\r
1170         //\r
1171         // style is only valid when decimal formatter is constructed through\r
1172         // DecimalFormat(pattern, symbol, style)\r
1173         if (style == NumberFormat.PLURALCURRENCYSTYLE) {\r
1174             // May need to reset pattern if the style is PLURALCURRENCYSTYLE.\r
1175             String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);\r
1176             if (formatPattern.equals(currencyPluralPattern) == false) {\r
1177                 applyPatternWithoutExpandAffix(currencyPluralPattern, false);\r
1178             }\r
1179         }\r
1180         // Expand the affix to the right name according to the plural rule.  This is only\r
1181         // used for currency plural formatting.  Currency plural name is not a fixed\r
1182         // static one, it is a dynamic name based on the currency plural count.  So, the\r
1183         // affixes need to be expanded here.  For other cases, the affix is a static one\r
1184         // based on pattern alone, and it is already expanded during applying pattern, or\r
1185         // setDecimalFormatSymbols, or setCurrency.\r
1186         expandAffixAdjustWidth(pluralCount);\r
1187         return subformat(result, fieldPosition, isNegative, isInteger, parseAttr);\r
1188     }\r
1189 \r
1190     /**\r
1191      * Complete the formatting of a finite number. On entry, the\r
1192      * digitList must be filled in with the correct digits.\r
1193      */\r
1194     private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,\r
1195                                    boolean isNegative, boolean isInteger, boolean parseAttr) {\r
1196         // NOTE: This isn't required anymore because DigitList takes care of this.\r
1197         //\r
1198         // // The negative of the exponent represents the number of leading // zeros\r
1199         // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g.,\r
1200         // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction\r
1201         // digits, then we have an underflow // for the printed representation. We\r
1202         // recognize this here and set // the DigitList representation to zero in this\r
1203         // situation.\r
1204         //\r
1205         // if (-digitList.decimalAt >= getMaximumFractionDigits())\r
1206         // {\r
1207         // digitList.count = 0;\r
1208         // }\r
1209 \r
1210         int i;\r
1211         char zero = symbols.getZeroDigit();\r
1212         int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero\r
1213         char grouping = currencySignCount > 0 ? symbols.getMonetaryGroupingSeparator() :\r
1214             symbols.getGroupingSeparator();\r
1215         char decimal = currencySignCount > 0 ? symbols.getMonetaryDecimalSeparator() :\r
1216             symbols.getDecimalSeparator();\r
1217         boolean useSigDig = areSignificantDigitsUsed();\r
1218         int maxIntDig = getMaximumIntegerDigits();\r
1219         int minIntDig = getMinimumIntegerDigits();\r
1220 \r
1221         // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as\r
1222         // zero. This allows sensible computations and preserves relations such as\r
1223         // signum(1/x) = signum(x), where x is +Infinity or -Infinity.  Prior to this fix,\r
1224         // we always formatted zero values as if they were positive. Liu 7/6/98.\r
1225         if (digitList.isZero()) {\r
1226             digitList.decimalAt = 0; // Normalize\r
1227         }\r
1228 \r
1229         int prefixLen = appendAffix(result, isNegative, true, parseAttr);\r
1230 \r
1231         if (useExponentialNotation) {\r
1232             // Record field information for caller.\r
1233             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
1234                 fieldPosition.setBeginIndex(result.length());\r
1235                 fieldPosition.setEndIndex(-1);\r
1236             } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {\r
1237                 fieldPosition.setBeginIndex(-1);\r
1238             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
1239                 fieldPosition.setBeginIndex(result.length());\r
1240                 fieldPosition.setEndIndex(-1);\r
1241             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {\r
1242                 fieldPosition.setBeginIndex(-1);\r
1243             }\r
1244 \r
1245             // [Spark/CDL]\r
1246             // the begin index of integer part\r
1247             // the end index of integer part\r
1248             // the begin index of fractional part\r
1249             int intBegin = result.length();\r
1250             int intEnd = -1;\r
1251             int fracBegin = -1;\r
1252             int minFracDig = 0;\r
1253             if (useSigDig) {\r
1254                 maxIntDig = minIntDig = 1;\r
1255                 minFracDig = getMinimumSignificantDigits() - 1;\r
1256             } else {\r
1257                 minFracDig = getMinimumFractionDigits();\r
1258                 if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {\r
1259                     maxIntDig = 1;\r
1260                     if (maxIntDig < minIntDig) {\r
1261                         maxIntDig = minIntDig;\r
1262                     }\r
1263                 }\r
1264                 if (maxIntDig > minIntDig) {\r
1265                     minIntDig = 1;\r
1266                 }\r
1267             }\r
1268 \r
1269             // Minimum integer digits are handled in exponential format by adjusting the\r
1270             // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4".\r
1271 \r
1272             // Maximum integer digits are interpreted as indicating the repeating\r
1273             // range. This is useful for engineering notation, in which the exponent is\r
1274             // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer\r
1275             // digits is "12.34e-3".  If maximum integer digits are defined and are larger\r
1276             // than minimum integer digits, then minimum integer digits are ignored.\r
1277 \r
1278             int exponent = digitList.decimalAt;\r
1279             if (maxIntDig > 1 && maxIntDig != minIntDig) {\r
1280                 // A exponent increment is defined; adjust to it.\r
1281                 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1;\r
1282                 exponent *= maxIntDig;\r
1283             } else {\r
1284                 // No exponent increment is defined; use minimum integer digits.\r
1285                 // If none is specified, as in "#E0", generate 1 integer digit.\r
1286                 exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1;\r
1287             }\r
1288 \r
1289             // We now output a minimum number of digits, and more if there are more\r
1290             // digits, up to the maximum number of digits. We place the decimal point\r
1291             // after the "integer" digits, which are the first (decimalAt - exponent)\r
1292             // digits.\r
1293             int minimumDigits = minIntDig + minFracDig;\r
1294             // The number of integer digits is handled specially if the number\r
1295             // is zero, since then there may be no digits.\r
1296             int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent;\r
1297             int totalDigits = digitList.count;\r
1298             if (minimumDigits > totalDigits)\r
1299                 totalDigits = minimumDigits;\r
1300             if (integerDigits > totalDigits)\r
1301                 totalDigits = integerDigits;\r
1302 \r
1303             for (i = 0; i < totalDigits; ++i) {\r
1304                 if (i == integerDigits) {\r
1305                     // Record field information for caller.\r
1306                     if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
1307                         fieldPosition.setEndIndex(result.length());\r
1308                     } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
1309                         fieldPosition.setEndIndex(result.length());\r
1310                     }\r
1311 \r
1312                     // [Spark/CDL] Add attribute for integer part\r
1313                     if (parseAttr) {\r
1314                         intEnd = result.length();\r
1315                         addAttribute(Field.INTEGER, intBegin, result.length());\r
1316                     }\r
1317                     result.append(decimal);\r
1318                     // [Spark/CDL] Add attribute for decimal separator\r
1319                     if (parseAttr) {\r
1320                         // Length of decimal separator is 1.\r
1321                         int decimalSeparatorBegin = result.length() - 1;\r
1322                         addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin,\r
1323                                      result.length());\r
1324                         fracBegin = result.length();\r
1325                     }\r
1326                     // Record field information for caller.\r
1327                     if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {\r
1328                         fieldPosition.setBeginIndex(result.length());\r
1329                     } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {\r
1330                         fieldPosition.setBeginIndex(result.length());\r
1331                     }\r
1332                 }\r
1333                 result.append((i < digitList.count)\r
1334                               ? (char) (digitList.digits[i] + zeroDelta)\r
1335                               : zero);\r
1336             }\r
1337 \r
1338             // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL]\r
1339             if (digitList.isZero() && (totalDigits == 0)) {\r
1340                 result.append(zero);\r
1341             }\r
1342 \r
1343             // Record field information\r
1344             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
1345                 if (fieldPosition.getEndIndex() < 0) {\r
1346                     fieldPosition.setEndIndex(result.length());\r
1347                 }\r
1348             } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {\r
1349                 if (fieldPosition.getBeginIndex() < 0) {\r
1350                     fieldPosition.setBeginIndex(result.length());\r
1351                 }\r
1352                 fieldPosition.setEndIndex(result.length());\r
1353             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
1354                 if (fieldPosition.getEndIndex() < 0) {\r
1355                     fieldPosition.setEndIndex(result.length());\r
1356                 }\r
1357             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {\r
1358                 if (fieldPosition.getBeginIndex() < 0) {\r
1359                     fieldPosition.setBeginIndex(result.length());\r
1360                 }\r
1361                 fieldPosition.setEndIndex(result.length());\r
1362             }\r
1363 \r
1364             // [Spark/CDL] Calcuate the end index of integer part and fractional\r
1365             // part if they are not properly processed yet.\r
1366             if (parseAttr) {\r
1367                 if (intEnd < 0) {\r
1368                     addAttribute(Field.INTEGER, intBegin, result.length());\r
1369                 }\r
1370                 if (fracBegin > 0) {\r
1371                     addAttribute(Field.FRACTION, fracBegin, result.length());\r
1372                 }\r
1373             }\r
1374 \r
1375             // The exponent is output using the pattern-specified minimum exponent\r
1376             // digits. There is no maximum limit to the exponent digits, since truncating\r
1377             // the exponent would result in an unacceptable inaccuracy.\r
1378             result.append(symbols.getExponentSeparator());\r
1379             // [Spark/CDL] For exponent symbol, add an attribute.\r
1380             if (parseAttr) {\r
1381                 addAttribute(Field.EXPONENT_SYMBOL, result.length() -\r
1382                              symbols.getExponentSeparator().length(), result.length());\r
1383             }\r
1384             // For zero values, we force the exponent to zero. We must do this here, and\r
1385             // not earlier, because the value is used to determine integer digit count\r
1386             // above.\r
1387             if (digitList.isZero())\r
1388                 exponent = 0;\r
1389 \r
1390             boolean negativeExponent = exponent < 0;\r
1391             if (negativeExponent) {\r
1392                 exponent = -exponent;\r
1393                 result.append(symbols.getMinusSign());\r
1394                 // [Spark/CDL] If exponent has sign, then add an exponent sign\r
1395                 // attribute.\r
1396                 if (parseAttr) {\r
1397                     // Length of exponent sign is 1.\r
1398                     addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());\r
1399                 }\r
1400             } else if (exponentSignAlwaysShown) {\r
1401                 result.append(symbols.getPlusSign());\r
1402                 // [Spark/CDL] Add an plus sign attribute.\r
1403                 if (parseAttr) {\r
1404                     // Length of exponent sign is 1.\r
1405                     int expSignBegin = result.length() - 1;\r
1406                     addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length());\r
1407                 }\r
1408             }\r
1409             int expBegin = result.length();\r
1410             digitList.set(exponent);\r
1411             {\r
1412                 int expDig = minExponentDigits;\r
1413                 if (useExponentialNotation && expDig < 1) {\r
1414                     expDig = 1;\r
1415                 }\r
1416                 for (i = digitList.decimalAt; i < expDig; ++i)\r
1417                     result.append(zero);\r
1418             }\r
1419             for (i = 0; i < digitList.decimalAt; ++i) {\r
1420                 result.append((i < digitList.count) ? (char) (digitList.digits[i] + zeroDelta)\r
1421                               : zero);\r
1422             }\r
1423             // [Spark/CDL] Add attribute for exponent part.\r
1424             if (parseAttr) {\r
1425                 addAttribute(Field.EXPONENT, expBegin, result.length());\r
1426             }\r
1427         } else {\r
1428             // [Spark/CDL] Record the integer start index.\r
1429             int intBegin = result.length();\r
1430             // Record field information for caller.\r
1431             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
1432                 fieldPosition.setBeginIndex(result.length());\r
1433             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
1434                 fieldPosition.setBeginIndex(result.length());\r
1435             }\r
1436 \r
1437             int sigCount = 0;\r
1438             int minSigDig = getMinimumSignificantDigits();\r
1439             int maxSigDig = getMaximumSignificantDigits();\r
1440             if (!useSigDig) {\r
1441                 minSigDig = 0;\r
1442                 maxSigDig = Integer.MAX_VALUE;\r
1443             }\r
1444 \r
1445             // Output the integer portion. Here 'count' is the total number of integer\r
1446             // digits we will display, including both leading zeros required to satisfy\r
1447             // getMinimumIntegerDigits, and actual digits present in the number.\r
1448             int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig;\r
1449             if (digitList.decimalAt > 0 && count < digitList.decimalAt) {\r
1450                 count = digitList.decimalAt;\r
1451             }\r
1452 \r
1453             // Handle the case where getMaximumIntegerDigits() is smaller than the real\r
1454             // number of integer digits. If this is so, we output the least significant\r
1455             // max integer digits. For example, the value 1997 printed with 2 max integer\r
1456             // digits is just "97".\r
1457 \r
1458             int digitIndex = 0; // Index into digitList.fDigits[]\r
1459             if (count > maxIntDig && maxIntDig >= 0) {\r
1460                 count = maxIntDig;\r
1461                 digitIndex = digitList.decimalAt - count;\r
1462             }\r
1463 \r
1464             int sizeBeforeIntegerPart = result.length();\r
1465             for (i = count - 1; i >= 0; --i) {\r
1466                 if (i < digitList.decimalAt && digitIndex < digitList.count\r
1467                     && sigCount < maxSigDig) {\r
1468                     // Output a real digit\r
1469                     byte d = digitList.digits[digitIndex++];\r
1470                     result.append((char) (d + zeroDelta));\r
1471                     ++sigCount;\r
1472                 } else {\r
1473                     // Output a zero (leading or trailing)\r
1474                     result.append(zero);\r
1475                     if (sigCount > 0) {\r
1476                         ++sigCount;\r
1477                     }\r
1478                 }\r
1479 \r
1480                 // Output grouping separator if necessary.\r
1481                 if (isGroupingPosition(i)) {\r
1482                     result.append(grouping);\r
1483                     // [Spark/CDL] Add grouping separator attribute here.\r
1484                     if (parseAttr) {\r
1485                         // Length of grouping separator is 1.\r
1486                         addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());\r
1487                     }\r
1488                 }\r
1489             }\r
1490 \r
1491             // Record field information for caller.\r
1492             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {\r
1493                 fieldPosition.setEndIndex(result.length());\r
1494             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {\r
1495                 fieldPosition.setEndIndex(result.length());\r
1496             }\r
1497 \r
1498             // Determine whether or not there are any printable fractional digits. If\r
1499             // we've used up the digits we know there aren't.\r
1500             boolean fractionPresent = (!isInteger && digitIndex < digitList.count)\r
1501                     || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0));\r
1502 \r
1503             // If there is no fraction present, and we haven't printed any integer digits,\r
1504             // then print a zero. Otherwise we won't print _any_ digits, and we won't be\r
1505             // able to parse this string.\r
1506             if (!fractionPresent && result.length() == sizeBeforeIntegerPart)\r
1507                 result.append(zero);\r
1508             // [Spark/CDL] Add attribute for integer part.\r
1509             if (parseAttr) {\r
1510                 addAttribute(Field.INTEGER, intBegin, result.length());\r
1511             }\r
1512             // Output the decimal separator if we always do so.\r
1513             if (decimalSeparatorAlwaysShown || fractionPresent) {\r
1514                 result.append(decimal);\r
1515                 // [Spark/CDL] Add attribute for decimal separator\r
1516                 if (parseAttr) {\r
1517                     addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length());\r
1518                 }\r
1519             }\r
1520 \r
1521             // Record field information for caller.\r
1522             if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {\r
1523                 fieldPosition.setBeginIndex(result.length());\r
1524             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {\r
1525                 fieldPosition.setBeginIndex(result.length());\r
1526             }\r
1527 \r
1528             // [Spark/CDL] Record the begin index of fraction part.\r
1529             int fracBegin = result.length();\r
1530 \r
1531             count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits();\r
1532             if (useSigDig && (sigCount == maxSigDig ||\r
1533                               (sigCount >= minSigDig && digitIndex == digitList.count))) {\r
1534                 count = 0;\r
1535             }\r
1536             for (i = 0; i < count; ++i) {\r
1537                 // Here is where we escape from the loop. We escape if we've output the\r
1538                 // maximum fraction digits (specified in the for expression above). We\r
1539                 // also stop when we've output the minimum digits and either: we have an\r
1540                 // integer, so there is no fractional stuff to display, or we're out of\r
1541                 // significant digits.\r
1542                 if (!useSigDig && i >= getMinimumFractionDigits() &&\r
1543                     (isInteger || digitIndex >= digitList.count)) {\r
1544                     break;\r
1545                 }\r
1546 \r
1547                 // Output leading fractional zeros. These are zeros that come after the\r
1548                 // decimal but before any significant digits. These are only output if\r
1549                 // abs(number being formatted) < 1.0.\r
1550                 if (-1 - i > (digitList.decimalAt - 1)) {\r
1551                     result.append(zero);\r
1552                     continue;\r
1553                 }\r
1554 \r
1555                 // Output a digit, if we have any precision left, or a zero if we\r
1556                 // don't. We don't want to output noise digits.\r
1557                 if (!isInteger && digitIndex < digitList.count) {\r
1558                     result.append((char) (digitList.digits[digitIndex++] + zeroDelta));\r
1559                 } else {\r
1560                     result.append(zero);\r
1561                 }\r
1562 \r
1563                 // If we reach the maximum number of significant digits, or if we output\r
1564                 // all the real digits and reach the minimum, then we are done.\r
1565                 ++sigCount;\r
1566                 if (useSigDig && (sigCount == maxSigDig ||\r
1567                                   (digitIndex == digitList.count && sigCount >= minSigDig))) {\r
1568                     break;\r
1569                 }\r
1570             }\r
1571 \r
1572             // Record field information for caller.\r
1573             if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) {\r
1574                 fieldPosition.setEndIndex(result.length());\r
1575             } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) {\r
1576                 fieldPosition.setEndIndex(result.length());\r
1577             }\r
1578 \r
1579             // [Spark/CDL] Add attribute information if necessary.\r
1580             if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) {\r
1581                 addAttribute(Field.FRACTION, fracBegin, result.length());\r
1582             }\r
1583         }\r
1584 \r
1585         int suffixLen = appendAffix(result, isNegative, false, parseAttr);\r
1586 \r
1587         addPadding(result, fieldPosition, prefixLen, suffixLen);\r
1588         return result;\r
1589     }\r
1590 \r
1591     private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen,\r
1592                                   int suffixLen) {\r
1593         if (formatWidth > 0) {\r
1594             int len = formatWidth - result.length();\r
1595             if (len > 0) {\r
1596                 char[] padding = new char[len];\r
1597                 for (int i = 0; i < len; ++i) {\r
1598                     padding[i] = pad;\r
1599                 }\r
1600                 switch (padPosition) {\r
1601                 case PAD_AFTER_PREFIX:\r
1602                     result.insert(prefixLen, padding);\r
1603                     break;\r
1604                 case PAD_BEFORE_PREFIX:\r
1605                     result.insert(0, padding);\r
1606                     break;\r
1607                 case PAD_BEFORE_SUFFIX:\r
1608                     result.insert(result.length() - suffixLen, padding);\r
1609                     break;\r
1610                 case PAD_AFTER_SUFFIX:\r
1611                     result.append(padding);\r
1612                     break;\r
1613                 }\r
1614                 if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) {\r
1615                     fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len);\r
1616                     fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len);\r
1617                 }\r
1618             }\r
1619         }\r
1620     }\r
1621 \r
1622     /**\r
1623      * Parses the given string, returning a <code>Number</code> object to represent the\r
1624      * parsed value. <code>Double</code> objects are returned to represent non-integral\r
1625      * values which cannot be stored in a <code>BigDecimal</code>. These are\r
1626      * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is\r
1627      * false (the default), all other values are returned as <code>Long</code>,\r
1628      * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of\r
1629      * preference. If {@link #isParseBigDecimal()} is true, all other values are returned\r
1630      * as <code>BigDecimal</code> valuse. If the parse fails, null is returned.\r
1631      *\r
1632      * @param text the string to be parsed\r
1633      * @param parsePosition defines the position where parsing is to begin, and upon\r
1634      * return, the position where parsing left off. If the position has not changed upon\r
1635      * return, then parsing failed.\r
1636      * @return a <code>Number</code> object with the parsed value or\r
1637      * <code>null</code> if the parse failed\r
1638      * @stable ICU 2.0\r
1639      */\r
1640     public Number parse(String text, ParsePosition parsePosition) {\r
1641         return (Number) parse(text, parsePosition, false);\r
1642     }\r
1643 \r
1644     /**\r
1645      * Parses text from the given string as a CurrencyAmount. Unlike the parse() method,\r
1646      * this method will attempt to parse a generic currency name, searching for a match of\r
1647      * this object's locale's currency display names, or for a 3-letter ISO currency\r
1648      * code. This method will fail if this format is not a currency format, that is, if it\r
1649      * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix.\r
1650      *\r
1651      * @param text the string to parse\r
1652      * @param pos input-output position; on input, the position within text to match; must\r
1653      *  have 0 <= pos.getIndex() < text.length(); on output, the position after the last\r
1654      *  matched character. If the parse fails, the position in unchanged upon output.\r
1655      * @return a CurrencyAmount, or null upon failure\r
1656      */\r
1657     CurrencyAmount parseCurrency(String text, ParsePosition pos) {\r
1658         return (CurrencyAmount) parse(text, pos, true);\r
1659     }\r
1660 \r
1661     /**\r
1662      * Parses the given text as either a Number or a CurrencyAmount.\r
1663      *\r
1664      * @param text the string to parse\r
1665      * @param parsePosition input-output position; on input, the position within text to\r
1666      * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after\r
1667      * the last matched character. If the parse fails, the position in unchanged upon\r
1668      * output.\r
1669      * @param parseCurrency if true, a CurrencyAmount is parsed and returned; otherwise a\r
1670      * Number is parsed and returned\r
1671      * @return a Number or CurrencyAmount or null\r
1672      */\r
1673     private Object parse(String text, ParsePosition parsePosition, boolean parseCurrency) {\r
1674         int backup;\r
1675         int i = backup = parsePosition.getIndex();\r
1676 \r
1677         // Handle NaN as a special case:\r
1678 \r
1679         // Skip padding characters, if around prefix\r
1680         if (formatWidth > 0 &&\r
1681             (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) {\r
1682             i = skipPadding(text, i);\r
1683         }\r
1684         if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) {\r
1685             i += symbols.getNaN().length();\r
1686             // Skip padding characters, if around suffix\r
1687             if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX ||\r
1688                                     padPosition == PAD_AFTER_SUFFIX)) {\r
1689                 i = skipPadding(text, i);\r
1690             }\r
1691             parsePosition.setIndex(i);\r
1692             return new Double(Double.NaN);\r
1693         }\r
1694 \r
1695         // NaN parse failed; start over\r
1696         i = backup;\r
1697 \r
1698         boolean[] status = new boolean[STATUS_LENGTH];\r
1699         Currency[] currency = parseCurrency ? new Currency[1] : null;\r
1700         if (currencySignCount > 0) {\r
1701             if (!parseForCurrency(text, parsePosition, parseCurrency, currency, status)) {\r
1702                 return null;\r
1703             }\r
1704         } else {\r
1705             if (!subparse(text, parsePosition, digitList, false, status, currency, negPrefixPattern,\r
1706                           negSuffixPattern, posPrefixPattern, posSuffixPattern,\r
1707                           Currency.SYMBOL_NAME)) {\r
1708                 parsePosition.setIndex(backup);\r
1709                 return null;\r
1710             }\r
1711         }\r
1712 \r
1713         Number n = null;\r
1714 \r
1715         // Handle infinity\r
1716         if (status[STATUS_INFINITE]) {\r
1717             n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY :\r
1718                            Double.NEGATIVE_INFINITY);\r
1719         }\r
1720 \r
1721         // Handle underflow\r
1722         else if (status[STATUS_UNDERFLOW]) {\r
1723             n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0");\r
1724         }\r
1725 \r
1726         // Handle -0.0\r
1727         else if (!status[STATUS_POSITIVE] && digitList.isZero()) {\r
1728             n = new Double("-0.0");\r
1729         }\r
1730 \r
1731         else {\r
1732             // Do as much of the multiplier conversion as possible without\r
1733             // losing accuracy.\r
1734             int mult = multiplier; // Don't modify this.multiplier\r
1735             while (mult % 10 == 0) {\r
1736                 --digitList.decimalAt;\r
1737                 mult /= 10;\r
1738             }\r
1739 \r
1740             // Handle integral values\r
1741             if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) {\r
1742                 // hack quick long\r
1743                 if (digitList.decimalAt < 12) { // quick check for long\r
1744                     long l = 0;\r
1745                     if (digitList.count > 0) {\r
1746                         int nx = 0;\r
1747                         while (nx < digitList.count) {\r
1748                             l = l * 10 + (char) digitList.digits[nx++] - '0';\r
1749                         }\r
1750                         while (nx++ < digitList.decimalAt) {\r
1751                             l *= 10;\r
1752                         }\r
1753                         if (!status[STATUS_POSITIVE]) {\r
1754                             l = -l;\r
1755                         }\r
1756                     }\r
1757                     n = new Long(l);\r
1758                 } else {\r
1759                     BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]);\r
1760                     n = (big.bitLength() < 64) ? (Number) new Long(big.longValue()) : (Number) big;\r
1761                 }\r
1762             }\r
1763             // Handle non-integral values or the case where parseBigDecimal is set\r
1764             else {\r
1765                 BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]);\r
1766                 n = big;\r
1767                 if (mult != 1) {\r
1768                     n = big.divide(BigDecimal.valueOf(mult), mathContext);\r
1769                 }\r
1770             }\r
1771         }\r
1772 \r
1773         // Assemble into CurrencyAmount if necessary\r
1774         return parseCurrency ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n;\r
1775     }\r
1776 \r
1777     private boolean parseForCurrency(String text, ParsePosition parsePosition, boolean parseCurrency,\r
1778             Currency[] currency, boolean[] status) {\r
1779         int origPos = parsePosition.getIndex();\r
1780         if (!isReadyForParsing) {\r
1781             int savedCurrencySignCount = currencySignCount;\r
1782             setupCurrencyAffixForAllPatterns();\r
1783             // reset pattern back\r
1784             if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) {\r
1785                 applyPatternWithoutExpandAffix(formatPattern, false);\r
1786             } else {\r
1787                 applyPattern(formatPattern, false);\r
1788             }\r
1789             isReadyForParsing = true;\r
1790         }\r
1791         int maxPosIndex = origPos;\r
1792         int maxErrorPos = -1;\r
1793         boolean[] savedStatus = null;\r
1794         // First, parse against current pattern.\r
1795         // Since current pattern could be set by applyPattern(),\r
1796         // it could be an arbitrary pattern, and it may not be the one\r
1797         // defined in current locale.\r
1798         boolean[] tmpStatus = new boolean[STATUS_LENGTH];\r
1799         ParsePosition tmpPos = new ParsePosition(origPos);\r
1800         DigitList tmpDigitList = new DigitList();\r
1801         boolean found;\r
1802         if (style == NumberFormat.PLURALCURRENCYSTYLE) {\r
1803             found = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,\r
1804                              negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,\r
1805                              Currency.LONG_NAME);\r
1806         } else {\r
1807             found = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,\r
1808                              negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,\r
1809                              Currency.SYMBOL_NAME);\r
1810         }\r
1811         if (found) {\r
1812             if (tmpPos.getIndex() > maxPosIndex) {\r
1813                 maxPosIndex = tmpPos.getIndex();\r
1814                 savedStatus = tmpStatus;\r
1815                 digitList = tmpDigitList;\r
1816             }\r
1817         } else {\r
1818             maxErrorPos = tmpPos.getErrorIndex();\r
1819         }\r
1820         // Then, parse against affix patterns.  Those are currency patterns and currency\r
1821         // plural patterns defined in the locale.\r
1822         for (AffixForCurrency affix : affixPatternsForCurrency) {\r
1823             tmpStatus = new boolean[STATUS_LENGTH];\r
1824             tmpPos = new ParsePosition(origPos);\r
1825             tmpDigitList = new DigitList();\r
1826             boolean result = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,\r
1827                                       affix.getNegPrefix(), affix.getNegSuffix(),\r
1828                                       affix.getPosPrefix(), affix.getPosSuffix(),\r
1829                                       affix.getPatternType());\r
1830             if (result) {\r
1831                 found = true;\r
1832                 if (tmpPos.getIndex() > maxPosIndex) {\r
1833                     maxPosIndex = tmpPos.getIndex();\r
1834                     savedStatus = tmpStatus;\r
1835                     digitList = tmpDigitList;\r
1836                 }\r
1837             } else {\r
1838                 maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex()\r
1839                     : maxErrorPos;\r
1840             }\r
1841         }\r
1842         // Finally, parse against simple affix to find the match.  For example, in\r
1843         // TestMonster suite, if the to-be-parsed text is "-\u00A40,00".\r
1844         // complexAffixCompare will not find match, since there is no ISO code matches\r
1845         // "\u00A4", and the parse stops at "\u00A4".  We will just use simple affix\r
1846         // comparison (look for exact match) to pass it.\r
1847         tmpStatus = new boolean[STATUS_LENGTH];\r
1848         tmpPos = new ParsePosition(origPos);\r
1849         tmpDigitList = new DigitList();\r
1850         int savedCurrencySignCount = currencySignCount;\r
1851         // set currencySignCount to 0 so that compareAffix function will fall to\r
1852         // compareSimpleAffix path, not compareComplexAffix path.\r
1853         currencySignCount = 0;\r
1854         boolean result = subparse(text, tmpPos, tmpDigitList, false, tmpStatus, currency,\r
1855                                   negativePrefix, negativeSuffix, positivePrefix, positiveSuffix,\r
1856                                   Currency.SYMBOL_NAME);\r
1857         currencySignCount = savedCurrencySignCount;\r
1858         if (result) {\r
1859             if (tmpPos.getIndex() > maxPosIndex) {\r
1860                 maxPosIndex = tmpPos.getIndex();\r
1861                 savedStatus = tmpStatus;\r
1862                 digitList = tmpDigitList;\r
1863             }\r
1864             found = true;\r
1865         } else {\r
1866             maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() :\r
1867                 maxErrorPos;\r
1868         }\r
1869 \r
1870         if (!found) {\r
1871             // parsePosition.setIndex(origPos);\r
1872             parsePosition.setErrorIndex(maxErrorPos);\r
1873         } else {\r
1874             parsePosition.setIndex(maxPosIndex);\r
1875             parsePosition.setErrorIndex(-1);\r
1876             for (int index = 0; index < STATUS_LENGTH; ++index) {\r
1877                 status[index] = savedStatus[index];\r
1878             }\r
1879         }\r
1880         return found;\r
1881     }\r
1882 \r
1883     // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and\r
1884     // currency plural pattern (CurrencyUnitPatterns).\r
1885     private void setupCurrencyAffixForAllPatterns() {\r
1886         if (currencyPluralInfo == null) {\r
1887             currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());\r
1888         }\r
1889         affixPatternsForCurrency = new HashSet<AffixForCurrency>();\r
1890 \r
1891         // save the current pattern, since it will be changed by\r
1892         // applyPatternWithoutExpandAffix\r
1893         String savedFormatPattern = formatPattern;\r
1894 \r
1895         // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so,\r
1896         // only need to save one of them.  Here, chose onlyApplyPatternWithoutExpandAffix\r
1897         // without saving the actualy pattern in 'pattern' data member.  TODO: is it uloc?\r
1898         applyPatternWithoutExpandAffix(getPattern(symbols.getLocale(), NumberFormat.CURRENCYSTYLE),\r
1899                                        false);\r
1900         AffixForCurrency affixes = new AffixForCurrency(\r
1901             negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern,\r
1902             Currency.SYMBOL_NAME);\r
1903         affixPatternsForCurrency.add(affixes);\r
1904 \r
1905         // add plural pattern\r
1906         Iterator<String> iter = currencyPluralInfo.pluralPatternIterator();\r
1907         Set<String> currencyUnitPatternSet = new HashSet<String>();\r
1908         while (iter.hasNext()) {\r
1909             String pluralCount = iter.next();\r
1910             String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount);\r
1911             if (currencyPattern != null &&\r
1912                 currencyUnitPatternSet.contains(currencyPattern) == false) {\r
1913                 currencyUnitPatternSet.add(currencyPattern);\r
1914                 applyPatternWithoutExpandAffix(currencyPattern, false);\r
1915                 affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern,\r
1916                                                posSuffixPattern, Currency.LONG_NAME);\r
1917                 affixPatternsForCurrency.add(affixes);\r
1918             }\r
1919         }\r
1920         // reset pattern back\r
1921         formatPattern = savedFormatPattern;\r
1922     }\r
1923 \r
1924     private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1;\r
1925     private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2;\r
1926     private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3;\r
1927 \r
1928     private static final int STATUS_INFINITE = 0;\r
1929     private static final int STATUS_POSITIVE = 1;\r
1930     private static final int STATUS_UNDERFLOW = 2;\r
1931     private static final int STATUS_LENGTH = 3;\r
1932 \r
1933     private static final UnicodeSet dotEquivalents = new UnicodeSet(\r
1934             //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]"\r
1935             0x002E, 0x002E,\r
1936             0x2024, 0x2024,\r
1937             0x3002, 0x3002,\r
1938             0xFE12, 0xFE12,\r
1939             0xFE52, 0xFE52,\r
1940             0xFF0E, 0xFF0E,\r
1941             0xFF61, 0xFF61).freeze();\r
1942 \r
1943     private static final UnicodeSet commaEquivalents = new UnicodeSet(\r
1944             //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]"\r
1945             0x002C, 0x002C,\r
1946             0x060C, 0x060C,\r
1947             0x066B, 0x066B,\r
1948             0x3001, 0x3001,\r
1949             0xFE10, 0xFE11,\r
1950             0xFE50, 0xFE51,\r
1951             0xFF0C, 0xFF0C,\r
1952             0xFF64, 0xFF64).freeze();\r
1953 \r
1954 //    private static final UnicodeSet otherGroupingSeparators = new UnicodeSet(\r
1955 //            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"\r
1956 //            0x0020, 0x0020,\r
1957 //            0x0027, 0x0027,\r
1958 //            0x00A0, 0x00A0,\r
1959 //            0x066C, 0x066C,\r
1960 //            0x2000, 0x200A,\r
1961 //            0x2018, 0x2019,\r
1962 //            0x202F, 0x202F,\r
1963 //            0x205F, 0x205F,\r
1964 //            0x3000, 0x3000,\r
1965 //            0xFF07, 0xFF07).freeze();\r
1966 \r
1967     private static final UnicodeSet strictDotEquivalents = new UnicodeSet(\r
1968             //"[.\u2024\uFE52\uFF0E\uFF61]"\r
1969             0x002E, 0x002E,\r
1970             0x2024, 0x2024,\r
1971             0xFE52, 0xFE52,\r
1972             0xFF0E, 0xFF0E,\r
1973             0xFF61, 0xFF61).freeze();\r
1974 \r
1975     private static final UnicodeSet strictCommaEquivalents = new UnicodeSet(\r
1976             //"[,\u066B\uFE10\uFE50\uFF0C]"\r
1977             0x002C, 0x002C,\r
1978             0x066B, 0x066B,\r
1979             0xFE10, 0xFE10,\r
1980             0xFE50, 0xFE50,\r
1981             0xFF0C, 0xFF0C).freeze();\r
1982 \r
1983 //    private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet(\r
1984 //            //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]"\r
1985 //            0x0020, 0x0020,\r
1986 //            0x0027, 0x0027,\r
1987 //            0x00A0, 0x00A0,\r
1988 //            0x066C, 0x066C,\r
1989 //            0x2000, 0x200A,\r
1990 //            0x2018, 0x2019,\r
1991 //            0x202F, 0x202F,\r
1992 //            0x205F, 0x205F,\r
1993 //            0x3000, 0x3000,\r
1994 //            0xFF07, 0xFF07).freeze();\r
1995 \r
1996     private static final UnicodeSet defaultGroupingSeparators =\r
1997         // new UnicodeSet(dotEquivalents).addAll(commaEquivalents)\r
1998         //     .addAll(otherGroupingSeparators).freeze();\r
1999         new UnicodeSet(\r
2000                 0x0020, 0x0020,\r
2001                 0x0027, 0x0027,\r
2002                 0x002C, 0x002C,\r
2003                 0x002E, 0x002E,\r
2004                 0x00A0, 0x00A0,\r
2005                 0x060C, 0x060C,\r
2006                 0x066B, 0x066C,\r
2007                 0x2000, 0x200A,\r
2008                 0x2018, 0x2019,\r
2009                 0x2024, 0x2024,\r
2010                 0x202F, 0x202F,\r
2011                 0x205F, 0x205F,\r
2012                 0x3000, 0x3002,\r
2013                 0xFE10, 0xFE12,\r
2014                 0xFE50, 0xFE52,\r
2015                 0xFF07, 0xFF07,\r
2016                 0xFF0C, 0xFF0C,\r
2017                 0xFF0E, 0xFF0E,\r
2018                 0xFF61, 0xFF61,\r
2019                 0xFF64, 0xFF64).freeze();\r
2020 \r
2021     private static final UnicodeSet strictDefaultGroupingSeparators =\r
2022         // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents)\r
2023         //     .addAll(strictOtherGroupingSeparators).freeze();\r
2024         new UnicodeSet(\r
2025                 0x0020, 0x0020,\r
2026                 0x0027, 0x0027,\r
2027                 0x002C, 0x002C,\r
2028                 0x002E, 0x002E,\r
2029                 0x00A0, 0x00A0,\r
2030                 0x066B, 0x066C,\r
2031                 0x2000, 0x200A,\r
2032                 0x2018, 0x2019,\r
2033                 0x2024, 0x2024,\r
2034                 0x202F, 0x202F,\r
2035                 0x205F, 0x205F,\r
2036                 0x3000, 0x3000,\r
2037                 0xFE10, 0xFE10,\r
2038                 0xFE50, 0xFE50,\r
2039                 0xFE52, 0xFE52,\r
2040                 0xFF07, 0xFF07,\r
2041                 0xFF0C, 0xFF0C,\r
2042                 0xFF0E, 0xFF0E,\r
2043                 0xFF61, 0xFF61).freeze();\r
2044 \r
2045     private static final UnicodeSet EMPTY_SET = new UnicodeSet().freeze();\r
2046 \r
2047     // When parsing a number with big exponential value, it requires to transform the\r
2048     // value into a string representation to construct BigInteger instance.  We want to\r
2049     // set the maximum size because it can easily trigger OutOfMemoryException.\r
2050     // PARSE_MAX_EXPONENT is currently set to 1000, which is much bigger than MAX_VALUE of\r
2051     // Double ( See the problem reported by ticket#5698\r
2052     private static final int PARSE_MAX_EXPONENT = 1000;\r
2053 \r
2054     /**\r
2055      * Parses the given text into a number. The text is parsed beginning at parsePosition,\r
2056      * until an unparseable character is seen.\r
2057      *\r
2058      * @param text the string to parse.\r
2059      * @param parsePosition the position at which to being parsing. Upon return, the first\r
2060      * unparseable character.\r
2061      * @param digits the DigitList to set to the parsed value.\r
2062      * @param isExponent If true, parse an exponent. This means no infinite values and\r
2063      * integer only.\r
2064      * @param status Upon return contains boolean status flags indicating whether the\r
2065      * value was infinite and whether it was positive.\r
2066      * @param currency return value for parsed currency, for generic currency parsing\r
2067      * mode, or null for normal parsing. In generic currency parsing mode, any currency is\r
2068      * parsed, not just the currency that this formatter is set to.\r
2069      * @param negPrefix negative prefix pattern\r
2070      * @param negSuffix negative suffix pattern\r
2071      * @param posPrefix positive prefix pattern\r
2072      * @param negSuffix negative suffix pattern\r
2073      * @param type type of currency to parse against, LONG_NAME only or not.\r
2074      */\r
2075     private final boolean subparse(\r
2076         String text, ParsePosition parsePosition, DigitList digits, boolean isExponent,\r
2077         boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix,\r
2078         String posSuffix, int type) {\r
2079 \r
2080         int position = parsePosition.getIndex();\r
2081         int oldStart = parsePosition.getIndex();\r
2082 \r
2083         // Match padding before prefix\r
2084         if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) {\r
2085             position = skipPadding(text, position);\r
2086         }\r
2087 \r
2088         // Match positive and negative prefixes; prefer longest match.\r
2089         int posMatch = compareAffix(text, position, false, true, posPrefix, type, currency);\r
2090         int negMatch = compareAffix(text, position, true, true, negPrefix, type, currency);\r
2091         if (posMatch >= 0 && negMatch >= 0) {\r
2092             if (posMatch > negMatch) {\r
2093                 negMatch = -1;\r
2094             } else if (negMatch > posMatch) {\r
2095                 posMatch = -1;\r
2096             }\r
2097         }\r
2098         if (posMatch >= 0) {\r
2099             position += posMatch;\r
2100         } else if (negMatch >= 0) {\r
2101             position += negMatch;\r
2102         } else {\r
2103             parsePosition.setErrorIndex(position);\r
2104             return false;\r
2105         }\r
2106 \r
2107         // Match padding after prefix\r
2108         if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) {\r
2109             position = skipPadding(text, position);\r
2110         }\r
2111 \r
2112         // process digits or Inf, find decimal position\r
2113         status[STATUS_INFINITE] = false;\r
2114         if (!isExponent && text.regionMatches(position, symbols.getInfinity(), 0,\r
2115                                               symbols.getInfinity().length())) {\r
2116             position += symbols.getInfinity().length();\r
2117             status[STATUS_INFINITE] = true;\r
2118         } else {\r
2119             // We now have a string of digits, possibly with grouping symbols, and decimal\r
2120             // points. We want to process these into a DigitList.  We don't want to put a\r
2121             // bunch of leading zeros into the DigitList though, so we keep track of the\r
2122             // location of the decimal point, put only significant digits into the\r
2123             // DigitList, and adjust the exponent as needed.\r
2124 \r
2125             digits.decimalAt = digits.count = 0;\r
2126             char zero = symbols.getZeroDigit();\r
2127             char decimal = currencySignCount > 0 ? symbols.getMonetaryDecimalSeparator() : symbols\r
2128                     .getDecimalSeparator();\r
2129             char grouping = symbols.getGroupingSeparator();\r
2130 \r
2131             String exponentSep = symbols.getExponentSeparator();\r
2132             boolean sawDecimal = false;\r
2133             boolean sawGrouping = false;\r
2134             boolean sawExponent = false;\r
2135             boolean sawDigit = false;\r
2136             long exponent = 0; // Set to the exponent value, if any\r
2137             int digit = 0;\r
2138 \r
2139             // strict parsing\r
2140             boolean strictParse = isParseStrict();\r
2141             boolean strictFail = false; // did we exit with a strict parse failure?\r
2142             int lastGroup = -1; // where did we last see a grouping separator?\r
2143             int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;\r
2144 \r
2145             // Strict parsing leading zeroes. If a leading zero would be forced by the\r
2146             // pattern, then don't fail strict parsing.\r
2147             boolean strictLeadingZero = false;\r
2148             int leadingZeroPos = 0;\r
2149             int leadingZeroCount = 0;\r
2150 \r
2151             // equivalent grouping and decimal support\r
2152             boolean skipExtendedSeparatorParsing = ICUConfig.get(\r
2153                 "com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")\r
2154                 .equals("true");\r
2155 \r
2156             UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? EMPTY_SET :\r
2157                 getEquivalentDecimals(decimal, strictParse);\r
2158             UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? EMPTY_SET :\r
2159                 (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators);\r
2160 \r
2161             // We have to track digitCount ourselves, because digits.count will pin when\r
2162             // the maximum allowable digits is reached.\r
2163             int digitCount = 0;\r
2164 \r
2165             int backup = -1;\r
2166             for (; position < text.length(); ++position) {\r
2167                 char ch = text.charAt(position);\r
2168 \r
2169 \r
2170                 // We recognize all digit ranges, not only the Latin digit range\r
2171                 // '0'..'9'. We do so by using the UCharacter.digit() method, which\r
2172                 // converts a valid Unicode digit to the range 0..9.\r
2173                 //\r
2174                 // The character 'ch' may be a digit. If so, place its value from 0 to 9\r
2175                 // in 'digit'. First try using the locale digit, which may or MAY NOT be a\r
2176                 // standard Unicode digit range. If this fails, try using the standard\r
2177                 // Unicode digit ranges by calling UCharacter.digit(). If this also fails,\r
2178                 // digit will have a value outside the range 0..9.\r
2179                 digit = ch - zero;\r
2180                 if (digit < 0 || digit > 9)\r
2181                     digit = UCharacter.digit(ch, 10);\r
2182 \r
2183                 if (digit == 0) {\r
2184                     // Cancel out backup setting (see grouping handler below)\r
2185                     if (strictParse && backup != -1) {\r
2186                         // comma followed by digit, so group before comma is a secondary\r
2187                         // group. If there was a group separator before that, the group\r
2188                         // must == the secondary group length, else it can be <= the the\r
2189                         // secondary group length.\r
2190                         if ((lastGroup != -1 && backup - lastGroup - 1 != gs2)\r
2191                                 || (lastGroup == -1 && position - oldStart - 1 > gs2)) {\r
2192                             strictFail = true;\r
2193                             break;\r
2194                         }\r
2195                         lastGroup = backup;\r
2196                     }\r
2197                     backup = -1; // Do this BEFORE continue statement below!!!\r
2198                     sawDigit = true;\r
2199 \r
2200                     // Handle leading zeros\r
2201                     if (digits.count == 0) {\r
2202                         if (!sawDecimal) {\r
2203                             if (strictParse && !isExponent) {\r
2204                                 // Allow leading zeros in exponents\r
2205                                 // Count leading zeros for checking later\r
2206                                 if (!strictLeadingZero)\r
2207                                     leadingZeroPos = position + 1;\r
2208                                 strictLeadingZero = true;\r
2209                                 ++leadingZeroCount;\r
2210                             }\r
2211                             // Ignore leading zeros in integer part of number.\r
2212                             continue;\r
2213                         }\r
2214 \r
2215                         // If we have seen the decimal, but no significant digits yet,\r
2216                         // then we account for leading zeros by decrementing the\r
2217                         // digits.decimalAt into negative values.\r
2218                         --digits.decimalAt;\r
2219                     } else {\r
2220                         ++digitCount;\r
2221                         digits.append((char) (digit + '0'));\r
2222                     }\r
2223                 } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above\r
2224                 {\r
2225                     if (strictParse) {\r
2226                         if (backup != -1) {\r
2227                             if ((lastGroup != -1 && backup - lastGroup - 1 != gs2)\r
2228                                     || (lastGroup == -1 && position - oldStart - 1 > gs2)) {\r
2229                                 strictFail = true;\r
2230                                 break;\r
2231                             }\r
2232                             lastGroup = backup;\r
2233                         }\r
2234                     }\r
2235 \r
2236                     sawDigit = true;\r
2237                     ++digitCount;\r
2238                     digits.append((char) (digit + '0'));\r
2239 \r
2240                     // Cancel out backup setting (see grouping handler below)\r
2241                     backup = -1;\r
2242                 } else if (!isExponent && ch == decimal) {\r
2243                     if (strictParse) {\r
2244                         if (backup != -1 ||\r
2245                             (lastGroup != -1 && position - lastGroup != groupingSize + 1)) {\r
2246                             strictFail = true;\r
2247                             break;\r
2248                         }\r
2249                     }\r
2250                     // If we're only parsing integers, or if we ALREADY saw the decimal,\r
2251                     // then don't parse this one.\r
2252                     if (isParseIntegerOnly() || sawDecimal) {\r
2253                         break;\r
2254                     }\r
2255                     digits.decimalAt = digitCount; // Not digits.count!\r
2256                     sawDecimal = true;\r
2257                 } else if (!isExponent && isGroupingUsed() && ch == grouping) {\r
2258                     if (sawDecimal) {\r
2259                         break;\r
2260                     }\r
2261                     if (strictParse) {\r
2262                         if ((!sawDigit || backup != -1)) {\r
2263                             // leading group, or two group separators in a row\r
2264                             strictFail = true;\r
2265                             break;\r
2266                         }\r
2267                     }\r
2268                     // Ignore grouping characters, if we are using them, but require that\r
2269                     // they be followed by a digit. Otherwise we backup and reprocess\r
2270                     // them.\r
2271                     backup = position;\r
2272                     sawGrouping = true;\r
2273                 } else if (!isExponent && !sawDecimal && decimalEquiv.contains(ch)) {\r
2274                     if (strictParse) {\r
2275                         if (backup != -1 ||\r
2276                             (lastGroup != -1 && position - lastGroup != groupingSize + 1)) {\r
2277                             strictFail = true;\r
2278                             break;\r
2279                         }\r
2280                     }\r
2281                     // If we're only parsing integers, then don't parse this one.\r
2282                     if (isParseIntegerOnly())\r
2283                         break;\r
2284                     digits.decimalAt = digitCount; // Not digits.count!\r
2285 \r
2286                     // Once we see a decimal separator character, we only accept that\r
2287                     // decimal separator character from then on.\r
2288                     decimal = ch;\r
2289                     sawDecimal = true;\r
2290                 } else if (!isExponent && isGroupingUsed() && !sawGrouping &&\r
2291                            groupEquiv.contains(ch)) {\r
2292                     if (sawDecimal) {\r
2293                         break;\r
2294                     }\r
2295                     if (strictParse) {\r
2296                         if ((!sawDigit || backup != -1)) {\r
2297                             // leading group, or two group separators in a row\r
2298                             strictFail = true;\r
2299                             break;\r
2300                         }\r
2301                     }\r
2302                     // Once we see a grouping character, we only accept that grouping\r
2303                     // character from then on.\r
2304                     grouping = ch;\r
2305 \r
2306                     // Ignore grouping characters, if we are using them, but require that\r
2307                     // they be followed by a digit. Otherwise we backup and reprocess\r
2308                     // them.\r
2309                     backup = position;\r
2310                     sawGrouping = true;\r
2311                 } else if (!isExponent && !sawExponent\r
2312                         && text.regionMatches(position, exponentSep, 0, exponentSep.length())) {\r
2313                     // Parse sign, if present\r
2314                     boolean negExp = false;\r
2315                     int pos = position + exponentSep.length();\r
2316                     if (pos < text.length()) {\r
2317                         ch = text.charAt(pos);\r
2318                         if (ch == symbols.getPlusSign()) {\r
2319                             ++pos;\r
2320                         } else if (ch == symbols.getMinusSign()) {\r
2321                             ++pos;\r
2322                             negExp = true;\r
2323                         }\r
2324                     }\r
2325 \r
2326                     DigitList exponentDigits = new DigitList();\r
2327                     exponentDigits.count = 0;\r
2328                     while (pos < text.length()) {\r
2329                         digit = text.charAt(pos) - zero;\r
2330                         if (digit < 0 || digit > 9) {\r
2331                             // Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"\r
2332                             // Should update reassign the value of 'ch' in the code: digit\r
2333                             // = Character.digit(ch, 10); [Richard/GCL]\r
2334                             digit = UCharacter.digit(text.charAt(pos), 10);\r
2335                         }\r
2336                         if (digit >= 0 && digit <= 9) {\r
2337                             exponentDigits.append((char) (digit + '0'));\r
2338                             ++pos;\r
2339                         } else {\r
2340                             break;\r
2341                         }\r
2342                     }\r
2343 \r
2344                     if (exponentDigits.count > 0) {\r
2345                         // defer strict parse until we know we have a bona-fide exponent\r
2346                         if (strictParse) {\r
2347                             if (backup != -1 || lastGroup != -1) {\r
2348                                 strictFail = true;\r
2349                                 break;\r
2350                             }\r
2351                         }\r
2352 \r
2353                         // Quick overflow check for exponential part.  Actual limit check\r
2354                         // will be done later in this code.\r
2355                         if (exponentDigits.count > 10 /* maximum decimal digits for int */) {\r
2356                             if (negExp) {\r
2357                                 // set underflow flag\r
2358                                 status[STATUS_UNDERFLOW] = true;\r
2359                             } else {\r
2360                                 // set infinite flag\r
2361                                 status[STATUS_INFINITE] = true;\r
2362                             }\r
2363                         } else {\r
2364                             exponentDigits.decimalAt = exponentDigits.count;\r
2365                             exponent = exponentDigits.getLong();\r
2366                             if (negExp) {\r
2367                                 exponent = -exponent;\r
2368                             }\r
2369                         }\r
2370                         position = pos; // Advance past the exponent\r
2371                         sawExponent = true;\r
2372                     }\r
2373 \r
2374                     break; // Whether we fail or succeed, we exit this loop\r
2375                 } else {\r
2376                     break;\r
2377                 }\r
2378             }\r
2379 \r
2380             if (backup != -1)\r
2381                 position = backup;\r
2382 \r
2383             // If there was no decimal point we have an integer\r
2384             if (!sawDecimal)\r
2385                 digits.decimalAt = digitCount; // Not digits.count!\r
2386 \r
2387             // check for strict parse errors\r
2388             if (strictParse && strictLeadingZero) {\r
2389                 if ((leadingZeroCount + digits.decimalAt) > this.getMinimumIntegerDigits()) {\r
2390                     parsePosition.setIndex(oldStart);\r
2391                     parsePosition.setErrorIndex(leadingZeroPos);\r
2392                     return false;\r
2393                 }\r
2394             }\r
2395             if (strictParse && !sawDecimal) {\r
2396                 if (lastGroup != -1 && position - lastGroup != groupingSize + 1) {\r
2397                     strictFail = true;\r
2398                 }\r
2399             }\r
2400             if (strictFail) {\r
2401                 // only set with strictParse and a leading zero error leading zeros are an\r
2402                 // error with strict parsing except immediately before nondigit (except\r
2403                 // group separator followed by digit), or end of text.\r
2404 \r
2405                 parsePosition.setIndex(oldStart);\r
2406                 parsePosition.setErrorIndex(position);\r
2407                 return false;\r
2408             }\r
2409 \r
2410             // Adjust for exponent, if any\r
2411             exponent += digits.decimalAt;\r
2412             if (exponent < -PARSE_MAX_EXPONENT) {\r
2413                 status[STATUS_UNDERFLOW] = true;\r
2414             } else if (exponent > PARSE_MAX_EXPONENT) {\r
2415                 status[STATUS_INFINITE] = true;\r
2416             } else {\r
2417                 digits.decimalAt = (int) exponent;\r
2418             }\r
2419 \r
2420             // If none of the text string was recognized. For example, parse "x" with\r
2421             // pattern "#0.00" (return index and error index both 0) parse "$" with\r
2422             // pattern "$#0.00". (return index 0 and error index 1).\r
2423             if (!sawDigit && digitCount == 0) {\r
2424                 parsePosition.setIndex(oldStart);\r
2425                 parsePosition.setErrorIndex(oldStart);\r
2426                 return false;\r
2427             }\r
2428         }\r
2429 \r
2430         // Match padding before suffix\r
2431         if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) {\r
2432             position = skipPadding(text, position);\r
2433         }\r
2434 \r
2435         // Match positive and negative suffixes; prefer longest match.\r
2436         if (posMatch >= 0) {\r
2437             posMatch = compareAffix(text, position, false, false, posSuffix, type, currency);\r
2438         }\r
2439         if (negMatch >= 0) {\r
2440             negMatch = compareAffix(text, position, true, false, negSuffix, type, currency);\r
2441         }\r
2442         if (posMatch >= 0 && negMatch >= 0) {\r
2443             if (posMatch > negMatch) {\r
2444                 negMatch = -1;\r
2445             } else if (negMatch > posMatch) {\r
2446                 posMatch = -1;\r
2447             }\r
2448         }\r
2449 \r
2450         // Fail if neither or both\r
2451         if ((posMatch >= 0) == (negMatch >= 0)) {\r
2452             parsePosition.setErrorIndex(position);\r
2453             return false;\r
2454         }\r
2455 \r
2456         position += (posMatch >= 0 ? posMatch : negMatch);\r
2457 \r
2458         // Match padding after suffix\r
2459         if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) {\r
2460             position = skipPadding(text, position);\r
2461         }\r
2462 \r
2463         parsePosition.setIndex(position);\r
2464 \r
2465         status[STATUS_POSITIVE] = (posMatch >= 0);\r
2466 \r
2467         if (parsePosition.getIndex() == oldStart) {\r
2468             parsePosition.setErrorIndex(position);\r
2469             return false;\r
2470         }\r
2471         return true;\r
2472     }\r
2473 \r
2474     /**\r
2475      * Returns a set of characters equivalent to the given desimal separator used for\r
2476      * parsing number.  This method may return an empty set.\r
2477      */\r
2478     private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) {\r
2479         UnicodeSet equivSet = EMPTY_SET;\r
2480         if (strictParse) {\r
2481             if (strictDotEquivalents.contains(decimal)) {\r
2482                 equivSet = strictDotEquivalents;\r
2483             } else if (strictCommaEquivalents.contains(decimal)) {\r
2484                 equivSet = strictCommaEquivalents;\r
2485             }\r
2486         } else {\r
2487             if (dotEquivalents.contains(decimal)) {\r
2488                 equivSet = dotEquivalents;\r
2489             } else if (commaEquivalents.contains(decimal)) {\r
2490                 equivSet = commaEquivalents;\r
2491             }\r
2492         }\r
2493         return equivSet;\r
2494     }\r
2495 \r
2496     /**\r
2497      * Starting at position, advance past a run of pad characters, if any. Return the\r
2498      * index of the first character after position that is not a pad character. Result is\r
2499      * >= position.\r
2500      */\r
2501     private final int skipPadding(String text, int position) {\r
2502         while (position < text.length() && text.charAt(position) == pad) {\r
2503             ++position;\r
2504         }\r
2505         return position;\r
2506     }\r
2507 \r
2508     /**\r
2509      * Returns the length matched by the given affix, or -1 if none. Runs of white space\r
2510      * in the affix, match runs of white space in the input. Pattern white space and input\r
2511      * white space are determined differently; see code.\r
2512      *\r
2513      * @param text input text\r
2514      * @param pos offset into input at which to begin matching\r
2515      * @param isNegative\r
2516      * @param isPrefix\r
2517      * @param affixPat affix pattern used for currency affix comparison\r
2518      * @param type compare against currency type, LONG_NAME only or not.\r
2519      * @param currency return value for parsed currency, for generic currency parsing\r
2520      * mode, or null for normal parsing.  In generic currency parsing mode, any currency\r
2521      * is parsed, not just the currency that this formatter is set to.\r
2522      * @return length of input that matches, or -1 if match failure\r
2523      */\r
2524     private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix,\r
2525                              String affixPat, int type, Currency[] currency) {\r
2526         if (currency != null || currencyChoice != null || currencySignCount > 0) {\r
2527             return compareComplexAffix(affixPat, text, pos, type, currency);\r
2528         }\r
2529         if (isPrefix) {\r
2530             return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos);\r
2531         } else {\r
2532             return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos);\r
2533         }\r
2534 \r
2535     }\r
2536 \r
2537     /**\r
2538      * Return the length matched by the given affix, or -1 if none. Runs of white space in\r
2539      * the affix, match runs of white space in the input. Pattern white space and input\r
2540      * white space are determined differently; see code.\r
2541      *\r
2542      * @param affix pattern string, taken as a literal\r
2543      * @param input input text\r
2544      * @param pos offset into input at which to begin matching\r
2545      * @return length of input that matches, or -1 if match failure\r
2546      */\r
2547     private static int compareSimpleAffix(String affix, String input, int pos) {\r
2548         int start = pos;\r
2549         for (int i = 0; i < affix.length();) {\r
2550             int c = UTF16.charAt(affix, i);\r
2551             int len = UTF16.getCharCount(c);\r
2552             if (UCharacterProperty.isRuleWhiteSpace(c)) {\r
2553                 // We may have a pattern like: \u200F and input text like: \u200F Note\r
2554                 // that U+200F and U+0020 are RuleWhiteSpace but only U+0020 is\r
2555                 // UWhiteSpace. So we have to first do a direct match of the run of RULE\r
2556                 // whitespace in the pattern, then match any extra characters.\r
2557                 boolean literalMatch = false;\r
2558                 while (pos < input.length() && UTF16.charAt(input, pos) == c) {\r
2559                     literalMatch = true;\r
2560                     i += len;\r
2561                     pos += len;\r
2562                     if (i == affix.length()) {\r
2563                         break;\r
2564                     }\r
2565                     c = UTF16.charAt(affix, i);\r
2566                     len = UTF16.getCharCount(c);\r
2567                     if (!UCharacterProperty.isRuleWhiteSpace(c)) {\r
2568                         break;\r
2569                     }\r
2570                 }\r
2571 \r
2572                 // Advance over run in affix\r
2573                 i = skipRuleWhiteSpace(affix, i);\r
2574 \r
2575                 // Advance over run in input text. Must see at least one white space char\r
2576                 // in input, unless we've already matched some characters literally.\r
2577                 int s = pos;\r
2578                 pos = skipUWhiteSpace(input, pos);\r
2579                 if (pos == s && !literalMatch) {\r
2580                     return -1;\r
2581                 }\r
2582                 // If we skip UWhiteSpace in the input text, we need to skip it in the\r
2583                 // pattern.  Otherwise, the previous lines may have skipped over text\r
2584                 // (such as U+00A0) that is also in the affix.\r
2585                 i = skipUWhiteSpace(affix, i);\r
2586             } else {\r
2587                 if (pos < input.length() && UTF16.charAt(input, pos) == c) {\r
2588                     i += len;\r
2589                     pos += len;\r
2590                 } else {\r
2591                     return -1;\r
2592                 }\r
2593             }\r
2594         }\r
2595         return pos - start;\r
2596     }\r
2597 \r
2598     /**\r
2599      * Skips over a run of zero or more isRuleWhiteSpace() characters at pos in text.\r
2600      */\r
2601     private static int skipRuleWhiteSpace(String text, int pos) {\r
2602         while (pos < text.length()) {\r
2603             int c = UTF16.charAt(text, pos);\r
2604             if (!UCharacterProperty.isRuleWhiteSpace(c)) {\r
2605                 break;\r
2606             }\r
2607             pos += UTF16.getCharCount(c);\r
2608         }\r
2609         return pos;\r
2610     }\r
2611 \r
2612     /**\r
2613      * Skips over a run of zero or more isUWhiteSpace() characters at pos in text.\r
2614      */\r
2615     private static int skipUWhiteSpace(String text, int pos) {\r
2616         while (pos < text.length()) {\r
2617             int c = UTF16.charAt(text, pos);\r
2618             if (!UCharacter.isUWhiteSpace(c)) {\r
2619                 break;\r
2620             }\r
2621             pos += UTF16.getCharCount(c);\r
2622         }\r
2623         return pos;\r
2624     }\r
2625 \r
2626     /**\r
2627      * Returns the length matched by the given affix, or -1 if none.\r
2628      *\r
2629      * @param affixPat pattern string\r
2630      * @param text input text\r
2631      * @param pos offset into input at which to begin matching\r
2632      * @param type parse against currency type, LONG_NAME only or not.\r
2633      * @param currency return value for parsed currency, for generic\r
2634      * currency parsing mode, or null for normal parsing.  In generic\r
2635      * currency parsing mode, any currency is parsed, not just the\r
2636      * currency that this formatter is set to.\r
2637      * @return position after the matched text, or -1 if match failure\r
2638      */\r
2639     private int compareComplexAffix(String affixPat, String text, int pos, int type,\r
2640                                     Currency[] currency) {\r
2641         int start = pos;\r
2642         for (int i = 0; i < affixPat.length() && pos >= 0;) {\r
2643             char c = affixPat.charAt(i++);\r
2644             if (c == QUOTE) {\r
2645                 for (;;) {\r
2646                     int j = affixPat.indexOf(QUOTE, i);\r
2647                     if (j == i) {\r
2648                         pos = match(text, pos, QUOTE);\r
2649                         i = j + 1;\r
2650                         break;\r
2651                     } else if (j > i) {\r
2652                         pos = match(text, pos, affixPat.substring(i, j));\r
2653                         i = j + 1;\r
2654                         if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) {\r
2655                             pos = match(text, pos, QUOTE);\r
2656                             ++i;\r
2657                             // loop again\r
2658                         } else {\r
2659                             break;\r
2660                         }\r
2661                     } else {\r
2662                         // Unterminated quote; should be caught by apply\r
2663                         // pattern.\r
2664                         throw new RuntimeException();\r
2665                     }\r
2666                 }\r
2667                 continue;\r
2668             }\r
2669 \r
2670             switch (c) {\r
2671             case CURRENCY_SIGN:\r
2672                 // since the currency names in choice format is saved the same way as\r
2673                 // other currency names, do not need to do currency choice parsing here.\r
2674                 // the general currency parsing parse against all names, including names\r
2675                 // in choice format.  assert(currency != null || (getCurrency() != null &&\r
2676                 // currencyChoice != null));\r
2677                 boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;\r
2678                 if (intl) {\r
2679                     ++i;\r
2680                 }\r
2681                 boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN;\r
2682                 if (plural) {\r
2683                     ++i;\r
2684                     intl = false;\r
2685                 }\r
2686                 // Parse generic currency -- anything for which we have a display name, or\r
2687                 // any 3-letter ISO code.  Try to parse display name for our locale; first\r
2688                 // determine our locale.  TODO: use locale in CurrencyPluralInfo\r
2689                 ULocale uloc = getLocale(ULocale.VALID_LOCALE);\r
2690                 if (uloc == null) {\r
2691                     // applyPattern has been called; use the symbols\r
2692                     uloc = symbols.getLocale(ULocale.VALID_LOCALE);\r
2693                 }\r
2694                 // Delegate parse of display name => ISO code to Currency\r
2695                 ParsePosition ppos = new ParsePosition(pos);\r
2696                 // using Currency.parse to handle mixed style parsing.\r
2697                 String iso = Currency.parse(uloc, text, type, ppos);\r
2698 \r
2699                 // If parse succeeds, populate currency[0]\r
2700                 if (iso != null) {\r
2701                     if (currency != null) {\r
2702                         currency[0] = Currency.getInstance(iso);\r
2703                     }\r
2704                     pos = ppos.getIndex();\r
2705                 } else {\r
2706                     pos = -1;\r
2707                 }\r
2708                 continue;\r
2709             case PATTERN_PERCENT:\r
2710                 c = symbols.getPercent();\r
2711                 break;\r
2712             case PATTERN_PER_MILLE:\r
2713                 c = symbols.getPerMill();\r
2714                 break;\r
2715             case PATTERN_MINUS:\r
2716                 c = symbols.getMinusSign();\r
2717                 break;\r
2718             }\r
2719             pos = match(text, pos, c);\r
2720             if (UCharacterProperty.isRuleWhiteSpace(c)) {\r
2721                 i = skipRuleWhiteSpace(affixPat, i);\r
2722             }\r
2723         }\r
2724 \r
2725         return pos - start;\r
2726     }\r
2727 \r
2728     /**\r
2729      * Matches a single character at text[pos] and return the index of the next character\r
2730      * upon success. Return -1 on failure. If isRuleWhiteSpace(ch) then match a run of\r
2731      * white space in text.\r
2732      */\r
2733     static final int match(String text, int pos, int ch) {\r
2734         if (pos >= text.length()) {\r
2735             return -1;\r
2736         }\r
2737         if (UCharacterProperty.isRuleWhiteSpace(ch)) {\r
2738             // Advance over run of white space in input text\r
2739             // Must see at least one white space char in input\r
2740             int s = pos;\r
2741             pos = skipRuleWhiteSpace(text, pos);\r
2742             if (pos == s) {\r
2743                 return -1;\r
2744             }\r
2745             return pos;\r
2746         }\r
2747         return (pos >= 0 && UTF16.charAt(text, pos) == ch) ? (pos + UTF16.getCharCount(ch)) : -1;\r
2748     }\r
2749 \r
2750     /**\r
2751      * Matches a string at text[pos] and return the index of the next character upon\r
2752      * success. Return -1 on failure. Match a run of white space in str with a run of\r
2753      * white space in text.\r
2754      */\r
2755     static final int match(String text, int pos, String str) {\r
2756         for (int i = 0; i < str.length() && pos >= 0;) {\r
2757             int ch = UTF16.charAt(str, i);\r
2758             i += UTF16.getCharCount(ch);\r
2759             pos = match(text, pos, ch);\r
2760             if (UCharacterProperty.isRuleWhiteSpace(ch)) {\r
2761                 i = skipRuleWhiteSpace(str, i);\r
2762             }\r
2763         }\r
2764         return pos;\r
2765     }\r
2766 \r
2767     /**\r
2768      * Returns a copy of the decimal format symbols used by this format.\r
2769      *\r
2770      * @return desired DecimalFormatSymbols\r
2771      * @see DecimalFormatSymbols\r
2772      * @stable ICU 2.0\r
2773      */\r
2774     public DecimalFormatSymbols getDecimalFormatSymbols() {\r
2775         try {\r
2776             // don't allow multiple references\r
2777             return (DecimalFormatSymbols) symbols.clone();\r
2778         } catch (Exception foo) {\r
2779             return null; // should never happen\r
2780         }\r
2781     }\r
2782 \r
2783     /**\r
2784      * Sets the decimal format symbols used by this format. The format uses a copy of the\r
2785      * provided symbols.\r
2786      *\r
2787      * @param newSymbols desired DecimalFormatSymbols\r
2788      * @see DecimalFormatSymbols\r
2789      * @stable ICU 2.0\r
2790      */\r
2791     public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {\r
2792         symbols = (DecimalFormatSymbols) newSymbols.clone();\r
2793         setCurrencyForSymbols();\r
2794         expandAffixes(null);\r
2795     }\r
2796 \r
2797     /**\r
2798      * Update the currency object to match the symbols. This method is used only when the\r
2799      * caller has passed in a symbols object that may not be the default object for its\r
2800      * locale.\r
2801      */\r
2802     private void setCurrencyForSymbols() {\r
2803 \r
2804         // Bug 4212072 Update the affix strings according to symbols in order to keep the\r
2805         // affix strings up to date.  [Richard/GCL]\r
2806 \r
2807         // With the introduction of the Currency object, the currency symbols in the DFS\r
2808         // object are ignored. For backward compatibility, we check any explicitly set DFS\r
2809         // object. If it is a default symbols object for its locale, we change the\r
2810         // currency object to one for that locale. If it is custom, we set the currency to\r
2811         // null.\r
2812         DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getLocale());\r
2813 \r
2814         if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol())\r
2815                 && symbols.getInternationalCurrencySymbol()\r
2816                        .equals(def.getInternationalCurrencySymbol())) {\r
2817             setCurrency(Currency.getInstance(symbols.getLocale()));\r
2818         } else {\r
2819             setCurrency(null);\r
2820         }\r
2821     }\r
2822 \r
2823     /**\r
2824      * Returns the positive prefix.\r
2825      *\r
2826      * <p>Examples: +123, $123, sFr123\r
2827      * @return the prefix\r
2828      * @stable ICU 2.0\r
2829      */\r
2830     public String getPositivePrefix() {\r
2831         return positivePrefix;\r
2832     }\r
2833 \r
2834     /**\r
2835      * Sets the positive prefix.\r
2836      *\r
2837      * <p>Examples: +123, $123, sFr123\r
2838      * @param newValue the prefix\r
2839      * @stable ICU 2.0\r
2840      */\r
2841     public void setPositivePrefix(String newValue) {\r
2842         positivePrefix = newValue;\r
2843         posPrefixPattern = null;\r
2844     }\r
2845 \r
2846     /**\r
2847      * Returns the negative prefix.\r
2848      *\r
2849      * <p>Examples: -123, ($123) (with negative suffix), sFr-123\r
2850      *\r
2851      * @return the prefix\r
2852      * @stable ICU 2.0\r
2853      */\r
2854     public String getNegativePrefix() {\r
2855         return negativePrefix;\r
2856     }\r
2857 \r
2858     /**\r
2859      * Sets the negative prefix.\r
2860      *\r
2861      * <p>Examples: -123, ($123) (with negative suffix), sFr-123\r
2862      * @param newValue the prefix\r
2863      * @stable ICU 2.0\r
2864      */\r
2865     public void setNegativePrefix(String newValue) {\r
2866         negativePrefix = newValue;\r
2867         negPrefixPattern = null;\r
2868     }\r
2869 \r
2870     /**\r
2871      * Returns the positive suffix.\r
2872      *\r
2873      * <p>Example: 123%\r
2874      *\r
2875      * @return the suffix\r
2876      * @stable ICU 2.0\r
2877      */\r
2878     public String getPositiveSuffix() {\r
2879         return positiveSuffix;\r
2880     }\r
2881 \r
2882     /**\r
2883      * Sets the positive suffix.\r
2884      *\r
2885      * <p>Example: 123%\r
2886      * @param newValue the suffix\r
2887      * @stable ICU 2.0\r
2888      */\r
2889     public void setPositiveSuffix(String newValue) {\r
2890         positiveSuffix = newValue;\r
2891         posSuffixPattern = null;\r
2892     }\r
2893 \r
2894     /**\r
2895      * Returns the negative suffix.\r
2896      *\r
2897      * <p>Examples: -123%, ($123) (with positive suffixes)\r
2898      *\r
2899      * @return the suffix\r
2900      * @stable ICU 2.0\r
2901      */\r
2902     public String getNegativeSuffix() {\r
2903         return negativeSuffix;\r
2904     }\r
2905 \r
2906     /**\r
2907      * Sets the positive suffix.\r
2908      *\r
2909      * <p>Examples: 123%\r
2910      * @param newValue the suffix\r
2911      * @stable ICU 2.0\r
2912      */\r
2913     public void setNegativeSuffix(String newValue) {\r
2914         negativeSuffix = newValue;\r
2915         negSuffixPattern = null;\r
2916     }\r
2917 \r
2918     /**\r
2919      * Returns the multiplier for use in percent, permill, etc. For a percentage, set the\r
2920      * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent\r
2921      * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be\r
2922      * 1000.\r
2923      *\r
2924      * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23\r
2925      *\r
2926      * @return the multiplier\r
2927      * @stable ICU 2.0\r
2928      */\r
2929     public int getMultiplier() {\r
2930         return multiplier;\r
2931     }\r
2932 \r
2933     /**\r
2934      * Sets the multiplier for use in percent, permill, etc. For a percentage, set the\r
2935      * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent\r
2936      * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be\r
2937      * 1000.\r
2938      *\r
2939      * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23\r
2940      *\r
2941      * @param newValue the multiplier\r
2942      * @stable ICU 2.0\r
2943      */\r
2944     public void setMultiplier(int newValue) {\r
2945         if (newValue == 0) {\r
2946             throw new IllegalArgumentException("Bad multiplier: " + newValue);\r
2947         }\r
2948         multiplier = newValue;\r
2949     }\r
2950 \r
2951     /**\r
2952      * {@icu} Returns the rounding increment.\r
2953      *\r
2954      * @return A positive rounding increment, or <code>null</code> if rounding is not in\r
2955      * effect.\r
2956      * @see #setRoundingIncrement\r
2957      * @see #getRoundingMode\r
2958      * @see #setRoundingMode\r
2959      * @stable ICU 2.0\r
2960      */\r
2961     public java.math.BigDecimal getRoundingIncrement() {\r
2962         if (roundingIncrementICU == null)\r
2963             return null;\r
2964         return roundingIncrementICU.toBigDecimal();\r
2965     }\r
2966 \r
2967     /**\r
2968      * {@icu} Sets the rounding increment. This method also controls whether rounding is\r
2969      * enabled.\r
2970      *\r
2971      * @param newValue A positive rounding increment, or <code>null</code> or\r
2972      * <code>BigDecimal(0.0)</code> to disable rounding.\r
2973      * @throws IllegalArgumentException if <code>newValue</code> is < 0.0\r
2974      * @see #getRoundingIncrement\r
2975      * @see #getRoundingMode\r
2976      * @see #setRoundingMode\r
2977      * @stable ICU 2.0\r
2978      */\r
2979     public void setRoundingIncrement(java.math.BigDecimal newValue) {\r
2980         if (newValue == null) {\r
2981             setRoundingIncrement((BigDecimal) null);\r
2982         } else {\r
2983             setRoundingIncrement(new BigDecimal(newValue));\r
2984         }\r
2985     }\r
2986 \r
2987     /**\r
2988      * {@icu} Sets the rounding increment. This method also controls whether rounding is\r
2989      * enabled.\r
2990      *\r
2991      * @param newValue A positive rounding increment, or <code>null</code> or\r
2992      * <code>BigDecimal(0.0)</code> to disable rounding.\r
2993      * @throws IllegalArgumentException if <code>newValue</code> is < 0.0\r
2994      * @see #getRoundingIncrement\r
2995      * @see #getRoundingMode\r
2996      * @see #setRoundingMode\r
2997      * @stable ICU 3.6\r
2998      */\r
2999     public void setRoundingIncrement(BigDecimal newValue) {\r
3000         int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO);\r
3001         if (i < 0) {\r
3002             throw new IllegalArgumentException("Illegal rounding increment");\r
3003         }\r
3004         if (i == 0) {\r
3005             setInternalRoundingIncrement(null);\r
3006         } else {\r
3007             setInternalRoundingIncrement(newValue);\r
3008         }\r
3009         setRoundingDouble();\r
3010     }\r
3011 \r
3012     /**\r
3013      * {@icu} Sets the rounding increment. This method also controls whether rounding is\r
3014      * enabled.\r
3015      *\r
3016      * @param newValue A positive rounding increment, or 0.0 to disable rounding.\r
3017      * @throws IllegalArgumentException if <code>newValue</code> is < 0.0\r
3018      * @see #getRoundingIncrement\r
3019      * @see #getRoundingMode\r
3020      * @see #setRoundingMode\r
3021      * @stable ICU 2.0\r
3022      */\r
3023     public void setRoundingIncrement(double newValue) {\r
3024         if (newValue < 0.0) {\r
3025             throw new IllegalArgumentException("Illegal rounding increment");\r
3026         }\r
3027         roundingDouble = newValue;\r
3028         roundingDoubleReciprocal = 0.0d;\r
3029         if (newValue == 0.0d) {\r
3030             setRoundingIncrement((BigDecimal) null);\r
3031         } else {\r
3032             roundingDouble = newValue;\r
3033             if (roundingDouble < 1.0d) {\r
3034                 double rawRoundedReciprocal = 1.0d / roundingDouble;\r
3035                 setRoundingDoubleReciprocal(rawRoundedReciprocal);\r
3036             }\r
3037             setInternalRoundingIncrement(new BigDecimal(newValue));\r
3038         }\r
3039     }\r
3040 \r
3041     private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) {\r
3042         roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal);\r
3043         if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) {\r
3044             roundingDoubleReciprocal = 0.0d;\r
3045         }\r
3046     }\r
3047 \r
3048     static final double roundingIncrementEpsilon = 0.000000001;\r
3049 \r
3050     /**\r
3051      * Returns the rounding mode.\r
3052      *\r
3053      * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and\r
3054      * <code>BigDecimal.ROUND_UNNECESSARY</code>.\r
3055      * @see #setRoundingIncrement\r
3056      * @see #getRoundingIncrement\r
3057      * @see #setRoundingMode\r
3058      * @see java.math.BigDecimal\r
3059      * @stable ICU 2.0\r
3060      */\r
3061     public int getRoundingMode() {\r
3062         return roundingMode;\r
3063     }\r
3064 \r
3065     /**\r
3066      * Sets the rounding mode. This has no effect unless the rounding increment is greater\r
3067      * than zero.\r
3068      *\r
3069      * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and\r
3070      * <code>BigDecimal.ROUND_UNNECESSARY</code>.\r
3071      * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.\r
3072      * @see #setRoundingIncrement\r
3073      * @see #getRoundingIncrement\r
3074      * @see #getRoundingMode\r
3075      * @see java.math.BigDecimal\r
3076      * @stable ICU 2.0\r
3077      */\r
3078     public void setRoundingMode(int roundingMode) {\r
3079         if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {\r
3080             throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);\r
3081         }\r
3082 \r
3083         this.roundingMode = roundingMode;\r
3084 \r
3085         if (getRoundingIncrement() == null) {\r
3086             setRoundingIncrement(Math.pow(10.0, (double) -getMaximumFractionDigits()));\r
3087         }\r
3088     }\r
3089 \r
3090     /**\r
3091      * Returns the width to which the output of <code>format()</code> is padded. The width is\r
3092      * counted in 16-bit code units.\r
3093      *\r
3094      * @return the format width, or zero if no padding is in effect\r
3095      * @see #setFormatWidth\r
3096      * @see #getPadCharacter\r
3097      * @see #setPadCharacter\r
3098      * @see #getPadPosition\r
3099      * @see #setPadPosition\r
3100      * @stable ICU 2.0\r
3101      */\r
3102     public int getFormatWidth() {\r
3103         return formatWidth;\r
3104     }\r
3105 \r
3106     /**\r
3107      * Sets the width to which the output of <code>format()</code> is\r
3108      * padded. The width is counted in 16-bit code units.  This method\r
3109      * also controls whether padding is enabled.\r
3110      *\r
3111      * @param width the width to which to pad the result of\r
3112      * <code>format()</code>, or zero to disable padding\r
3113      * @exception IllegalArgumentException if <code>width</code> is < 0\r
3114      * @see #getFormatWidth\r
3115      * @see #getPadCharacter\r
3116      * @see #setPadCharacter\r
3117      * @see #getPadPosition\r
3118      * @see #setPadPosition\r
3119      * @stable ICU 2.0\r
3120      */\r
3121     public void setFormatWidth(int width) {\r
3122         if (width < 0) {\r
3123             throw new IllegalArgumentException("Illegal format width");\r
3124         }\r
3125         formatWidth = width;\r
3126     }\r
3127 \r
3128     /**\r
3129      * {@icu} Returns the character used to pad to the format width. The default is ' '.\r
3130      *\r
3131      * @return the pad character\r
3132      * @see #setFormatWidth\r
3133      * @see #getFormatWidth\r
3134      * @see #setPadCharacter\r
3135      * @see #getPadPosition\r
3136      * @see #setPadPosition\r
3137      * @stable ICU 2.0\r
3138      */\r
3139     public char getPadCharacter() {\r
3140         return pad;\r
3141     }\r
3142 \r
3143     /**\r
3144      * {@icu} Sets the character used to pad to the format width. If padding is not\r
3145      * enabled, then this will take effect if padding is later enabled.\r
3146      *\r
3147      * @param padChar the pad character\r
3148      * @see #setFormatWidth\r
3149      * @see #getFormatWidth\r
3150      * @see #getPadCharacter\r
3151      * @see #getPadPosition\r
3152      * @see #setPadPosition\r
3153      * @stable ICU 2.0\r
3154      */\r
3155     public void setPadCharacter(char padChar) {\r
3156         pad = padChar;\r
3157     }\r
3158 \r
3159     /**\r
3160      * {@icu} Returns the position at which padding will take place. This is the location at\r
3161      * which padding will be inserted if the result of <code>format()</code> is shorter\r
3162      * than the format width.\r
3163      *\r
3164      * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>,\r
3165      *         <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or\r
3166      *         <code>PAD_AFTER_SUFFIX</code>.\r
3167      * @see #setFormatWidth\r
3168      * @see #getFormatWidth\r
3169      * @see #setPadCharacter\r
3170      * @see #getPadCharacter\r
3171      * @see #setPadPosition\r
3172      * @see #PAD_BEFORE_PREFIX\r
3173      * @see #PAD_AFTER_PREFIX\r
3174      * @see #PAD_BEFORE_SUFFIX\r
3175      * @see #PAD_AFTER_SUFFIX\r
3176      * @stable ICU 2.0\r
3177      */\r
3178     public int getPadPosition() {\r
3179         return padPosition;\r
3180     }\r
3181 \r
3182     /**\r
3183      * {@icu} Sets the position at which padding will take place. This is the location at\r
3184      * which padding will be inserted if the result of <code>format()</code> is shorter\r
3185      * than the format width. This has no effect unless padding is enabled.\r
3186      *\r
3187      * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>,\r
3188      * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or\r
3189      * <code>PAD_AFTER_SUFFIX</code>.\r
3190      * @exception IllegalArgumentException if the pad position in unrecognized\r
3191      * @see #setFormatWidth\r
3192      * @see #getFormatWidth\r
3193      * @see #setPadCharacter\r
3194      * @see #getPadCharacter\r
3195      * @see #getPadPosition\r
3196      * @see #PAD_BEFORE_PREFIX\r
3197      * @see #PAD_AFTER_PREFIX\r
3198      * @see #PAD_BEFORE_SUFFIX\r
3199      * @see #PAD_AFTER_SUFFIX\r
3200      * @stable ICU 2.0\r
3201      */\r
3202     public void setPadPosition(int padPos) {\r
3203         if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) {\r
3204             throw new IllegalArgumentException("Illegal pad position");\r
3205         }\r
3206         padPosition = padPos;\r
3207     }\r
3208 \r
3209     /**\r
3210      * {@icu} Returns whether or not scientific notation is used.\r
3211      *\r
3212      * @return true if this object formats and parses scientific notation\r
3213      * @see #setScientificNotation\r
3214      * @see #getMinimumExponentDigits\r
3215      * @see #setMinimumExponentDigits\r
3216      * @see #isExponentSignAlwaysShown\r
3217      * @see #setExponentSignAlwaysShown\r
3218      * @stable ICU 2.0\r
3219      */\r
3220     public boolean isScientificNotation() {\r
3221         return useExponentialNotation;\r
3222     }\r
3223 \r
3224     /**\r
3225      * {@icu} Sets whether or not scientific notation is used. When scientific notation is\r
3226      * used, the effective maximum number of integer digits is <= 8. If the maximum number\r
3227      * of integer digits is set to more than 8, the effective maximum will be 1. This\r
3228      * allows this call to generate a 'default' scientific number format without\r
3229      * additional changes.\r
3230      *\r
3231      * @param useScientific true if this object formats and parses scientific notation\r
3232      * @see #isScientificNotation\r
3233      * @see #getMinimumExponentDigits\r
3234      * @see #setMinimumExponentDigits\r
3235      * @see #isExponentSignAlwaysShown\r
3236      * @see #setExponentSignAlwaysShown\r
3237      * @stable ICU 2.0\r
3238      */\r
3239     public void setScientificNotation(boolean useScientific) {\r
3240         useExponentialNotation = useScientific;\r
3241     }\r
3242 \r
3243     /**\r
3244      * {@icu} Returns the minimum exponent digits that will be shown.\r
3245      *\r
3246      * @return the minimum exponent digits that will be shown\r
3247      * @see #setScientificNotation\r
3248      * @see #isScientificNotation\r
3249      * @see #setMinimumExponentDigits\r
3250      * @see #isExponentSignAlwaysShown\r
3251      * @see #setExponentSignAlwaysShown\r
3252      * @stable ICU 2.0\r
3253      */\r
3254     public byte getMinimumExponentDigits() {\r
3255         return minExponentDigits;\r
3256     }\r
3257 \r
3258     /**\r
3259      * {@icu} Sets the minimum exponent digits that will be shown. This has no effect\r
3260      * unless scientific notation is in use.\r
3261      *\r
3262      * @param minExpDig a value >= 1 indicating the fewest exponent\r
3263      * digits that will be shown\r
3264      * @exception IllegalArgumentException if <code>minExpDig</code> < 1\r
3265      * @see #setScientificNotation\r
3266      * @see #isScientificNotation\r
3267      * @see #getMinimumExponentDigits\r
3268      * @see #isExponentSignAlwaysShown\r
3269      * @see #setExponentSignAlwaysShown\r
3270      * @stable ICU 2.0\r
3271      */\r
3272     public void setMinimumExponentDigits(byte minExpDig) {\r
3273         if (minExpDig < 1) {\r
3274             throw new IllegalArgumentException("Exponent digits must be >= 1");\r
3275         }\r
3276         minExponentDigits = minExpDig;\r
3277     }\r
3278 \r
3279     /**\r
3280      * {@icu} Returns whether the exponent sign is always shown.\r
3281      *\r
3282      * @return true if the exponent is always prefixed with either the localized minus\r
3283      * sign or the localized plus sign, false if only negative exponents are prefixed with\r
3284      * the localized minus sign.\r
3285      * @see #setScientificNotation\r
3286      * @see #isScientificNotation\r
3287      * @see #setMinimumExponentDigits\r
3288      * @see #getMinimumExponentDigits\r
3289      * @see #setExponentSignAlwaysShown\r
3290      * @stable ICU 2.0\r
3291      */\r
3292     public boolean isExponentSignAlwaysShown() {\r
3293         return exponentSignAlwaysShown;\r
3294     }\r
3295 \r
3296     /**\r
3297      * {@icu} Sets whether the exponent sign is always shown. This has no effect unless\r
3298      * scientific notation is in use.\r
3299      *\r
3300      * @param expSignAlways true if the exponent is always prefixed with either the\r
3301      * localized minus sign or the localized plus sign, false if only negative exponents\r
3302      * are prefixed with the localized minus sign.\r
3303      * @see #setScientificNotation\r
3304      * @see #isScientificNotation\r
3305      * @see #setMinimumExponentDigits\r
3306      * @see #getMinimumExponentDigits\r
3307      * @see #isExponentSignAlwaysShown\r
3308      * @stable ICU 2.0\r
3309      */\r
3310     public void setExponentSignAlwaysShown(boolean expSignAlways) {\r
3311         exponentSignAlwaysShown = expSignAlways;\r
3312     }\r
3313 \r
3314     /**\r
3315      * Returns the grouping size. Grouping size is the number of digits between grouping\r
3316      * separators in the integer portion of a number. For example, in the number\r
3317      * "123,456.78", the grouping size is 3.\r
3318      *\r
3319      * @see #setGroupingSize\r
3320      * @see NumberFormat#isGroupingUsed\r
3321      * @see DecimalFormatSymbols#getGroupingSeparator\r
3322      * @stable ICU 2.0\r
3323      */\r
3324     public int getGroupingSize() {\r
3325         return groupingSize;\r
3326     }\r
3327 \r
3328     /**\r
3329      * Sets the grouping size. Grouping size is the number of digits between grouping\r
3330      * separators in the integer portion of a number. For example, in the number\r
3331      * "123,456.78", the grouping size is 3.\r
3332      *\r
3333      * @see #getGroupingSize\r
3334      * @see NumberFormat#setGroupingUsed\r
3335      * @see DecimalFormatSymbols#setGroupingSeparator\r
3336      * @stable ICU 2.0\r
3337      */\r
3338     public void setGroupingSize(int newValue) {\r
3339         groupingSize = (byte) newValue;\r
3340     }\r
3341 \r
3342     /**\r
3343      * {@icu} Returns the secondary grouping size. In some locales one grouping interval\r
3344      * is used for the least significant integer digits (the primary grouping size), and\r
3345      * another is used for all others (the secondary grouping size). A formatter\r
3346      * supporting a secondary grouping size will return a positive integer unequal to the\r
3347      * primary grouping size returned by <code>getGroupingSize()</code>. For example, if\r
3348      * the primary grouping size is 4, and the secondary grouping size is 2, then the\r
3349      * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0".\r
3350      *\r
3351      * @return the secondary grouping size, or a value less than one if there is none\r
3352      * @see #setSecondaryGroupingSize\r
3353      * @see NumberFormat#isGroupingUsed\r
3354      * @see DecimalFormatSymbols#getGroupingSeparator\r
3355      * @stable ICU 2.0\r
3356      */\r
3357     public int getSecondaryGroupingSize() {\r
3358         return groupingSize2;\r
3359     }\r
3360 \r
3361     /**\r
3362      * {@icu} Sets the secondary grouping size. If set to a value less than 1, then\r
3363      * secondary grouping is turned off, and the primary grouping size is used for all\r
3364      * intervals, not just the least significant.\r
3365      *\r
3366      * @see #getSecondaryGroupingSize\r
3367      * @see NumberFormat#setGroupingUsed\r
3368      * @see DecimalFormatSymbols#setGroupingSeparator\r
3369      * @stable ICU 2.0\r
3370      */\r
3371     public void setSecondaryGroupingSize(int newValue) {\r
3372         groupingSize2 = (byte) newValue;\r
3373     }\r
3374 \r
3375     /**\r
3376      * {@icu} Returns the MathContext used by this format.\r
3377      *\r
3378      * @return desired MathContext\r
3379      * @see #getMathContext\r
3380      * @stable ICU 4.2\r
3381      */\r
3382     public MathContext getMathContextICU() {\r
3383         return mathContext;\r
3384     }\r
3385 \r
3386     /**\r
3387      * {@icu} Returns the MathContext used by this format.\r
3388      *\r
3389      * @return desired MathContext\r
3390      * @see #getMathContext\r
3391      * @stable ICU 4.2\r
3392      */\r
3393     public java.math.MathContext getMathContext() {\r
3394         try {\r
3395             // don't allow multiple references\r
3396             return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(),\r
3397                     java.math.RoundingMode.valueOf(mathContext.getRoundingMode()));\r
3398         } catch (Exception foo) {\r
3399             return null; // should never happen\r
3400         }\r
3401     }\r
3402 \r
3403     /**\r
3404      * {@icu} Sets the MathContext used by this format.\r
3405      *\r
3406      * @param newValue desired MathContext\r
3407      * @see #getMathContext\r
3408      * @stable ICU 4.2\r
3409      */\r
3410     public void setMathContextICU(MathContext newValue) {\r
3411         mathContext = newValue;\r
3412     }\r
3413 \r
3414     /**\r
3415      * {@icu} Sets the MathContext used by this format.\r
3416      *\r
3417      * @param newValue desired MathContext\r
3418      * @see #getMathContext\r
3419      * @stable ICU 4.2\r
3420      */\r
3421     public void setMathContext(java.math.MathContext newValue) {\r
3422         mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false,\r
3423                                       (newValue.getRoundingMode()).ordinal());\r
3424     }\r
3425 \r
3426     /**\r
3427      * Returns the behavior of the decimal separator with integers. (The decimal\r
3428      * separator will always appear with decimals.)  <p> Example: Decimal ON: 12345 ->\r
3429      * 12345.; OFF: 12345 -> 12345\r
3430      *\r
3431      * @stable ICU 2.0\r
3432      */\r
3433     public boolean isDecimalSeparatorAlwaysShown() {\r
3434         return decimalSeparatorAlwaysShown;\r
3435     }\r
3436 \r
3437     /**\r
3438      * Sets the behavior of the decimal separator with integers. (The decimal separator\r
3439      * will always appear with decimals.)\r
3440      *\r
3441      * <p>This only affects formatting, and only where there might be no digits after the\r
3442      * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This\r
3443      * is independent of parsing. If you want parsing to stop at the decimal point, use\r
3444      * setParseIntegerOnly.\r
3445      *\r
3446      * <p>\r
3447      * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345\r
3448      *\r
3449      * @stable ICU 2.0\r
3450      */\r
3451     public void setDecimalSeparatorAlwaysShown(boolean newValue) {\r
3452         decimalSeparatorAlwaysShown = newValue;\r
3453     }\r
3454 \r
3455     /**\r
3456      * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might\r
3457      * return null if the decimal format is not a plural type currency decimal\r
3458      * format. Plural type currency decimal format means either the pattern in the decimal\r
3459      * format contains 3 currency signs, or the decimal format is initialized with\r
3460      * PLURALCURRENCYSTYLE.\r
3461      *\r
3462      * @return desired CurrencyPluralInfo\r
3463      * @see CurrencyPluralInfo\r
3464      * @stable ICU 4.2\r
3465      */\r
3466     public CurrencyPluralInfo getCurrencyPluralInfo() {\r
3467         try {\r
3468             // don't allow multiple references\r
3469             return currencyPluralInfo == null ? null :\r
3470                 (CurrencyPluralInfo) currencyPluralInfo.clone();\r
3471         } catch (Exception foo) {\r
3472             return null; // should never happen\r
3473         }\r
3474     }\r
3475 \r
3476     /**\r
3477      * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of\r
3478      * the provided information.\r
3479      *\r
3480      * @param newInfo desired CurrencyPluralInfo\r
3481      * @see CurrencyPluralInfo\r
3482      * @stable ICU 4.2\r
3483      */\r
3484     public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {\r
3485         currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone();\r
3486         isReadyForParsing = false;\r
3487     }\r
3488 \r
3489     /**\r
3490      * Overrides clone.\r
3491      * @stable ICU 2.0\r
3492      */\r
3493     public Object clone() {\r
3494         try {\r
3495             DecimalFormat other = (DecimalFormat) super.clone();\r
3496             other.symbols = (DecimalFormatSymbols) symbols.clone();\r
3497             other.digitList = new DigitList(); // fix for JB#5358\r
3498             if (currencyPluralInfo != null) {\r
3499                 other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();\r
3500             }\r
3501 \r
3502             // TODO: We need to figure out whether we share a single copy of DigitList by\r
3503             // multiple cloned copies.  format/subformat are designed to use a single\r
3504             // instance, but parse/subparse implementation is not.\r
3505             return other;\r
3506         } catch (Exception e) {\r
3507             throw new IllegalStateException();\r
3508         }\r
3509     }\r
3510 \r
3511     /**\r
3512      * Overrides equals.\r
3513      * @stable ICU 2.0\r
3514      */\r
3515     public boolean equals(Object obj) {\r
3516         if (obj == null)\r
3517             return false;\r
3518         if (!super.equals(obj))\r
3519             return false; // super does class check\r
3520 \r
3521         DecimalFormat other = (DecimalFormat) obj;\r
3522         // Add the comparison of the four new added fields ,they are posPrefixPattern,\r
3523         // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL]\r
3524         // following are added to accomodate changes for currency plural format.\r
3525         return currencySignCount == other.currencySignCount\r
3526                 && (style != NumberFormat.PLURALCURRENCYSTYLE ||\r
3527                     equals(posPrefixPattern, other.posPrefixPattern)\r
3528                 && equals(posSuffixPattern, other.posSuffixPattern)\r
3529                 && equals(negPrefixPattern, other.negPrefixPattern)\r
3530                 && equals(negSuffixPattern, other.negSuffixPattern))\r
3531                 && multiplier == other.multiplier\r
3532                 && groupingSize == other.groupingSize\r
3533                 && groupingSize2 == other.groupingSize2\r
3534                 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown\r
3535                 && useExponentialNotation == other.useExponentialNotation\r
3536                 && (!useExponentialNotation || minExponentDigits == other.minExponentDigits)\r
3537                 && useSignificantDigits == other.useSignificantDigits\r
3538                 && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits\r
3539                         && maxSignificantDigits == other.maxSignificantDigits)\r
3540                 && symbols.equals(other.symbols)\r
3541                 && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo);\r
3542     }\r
3543 \r
3544     // method to unquote the strings and compare\r
3545     private boolean equals(String pat1, String pat2) {\r
3546         if (pat1 == null || pat2 == null) {\r
3547             return (pat1 == null && pat2 == null);\r
3548         }\r
3549         // fast path\r
3550         if (pat1.equals(pat2)) {\r
3551             return true;\r
3552         }\r
3553         return unquote(pat1).equals(unquote(pat2));\r
3554     }\r
3555 \r
3556     private String unquote(String pat) {\r
3557         StringBuilder buf = new StringBuilder(pat.length());\r
3558         int i = 0;\r
3559         while (i < pat.length()) {\r
3560             char ch = pat.charAt(i++);\r
3561             if (ch != QUOTE) {\r
3562                 buf.append(ch);\r
3563             }\r
3564         }\r
3565         return buf.toString();\r
3566     }\r
3567 \r
3568     // protected void handleToString(StringBuffer buf) {\r
3569     // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n");\r
3570     // buf.append("positivePrefix: '" + positivePrefix + "'\n");\r
3571     // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n");\r
3572     // buf.append("positiveSuffix: '" + positiveSuffix + "'\n");\r
3573     // buf.append("negPrefixPattern: '" +\r
3574     //     com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n");\r
3575     // buf.append("negativePrefix: '" +\r
3576     //     com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n");\r
3577     // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n");\r
3578     // buf.append("negativeSuffix: '" + negativeSuffix + "'\n");\r
3579     // buf.append("multiplier: '" + multiplier + "'\n");\r
3580     // buf.append("groupingSize: '" + groupingSize + "'\n");\r
3581     // buf.append("groupingSize2: '" + groupingSize2 + "'\n");\r
3582     // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n");\r
3583     // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n");\r
3584     // buf.append("minExponentDigits: '" + minExponentDigits + "'\n");\r
3585     // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n");\r
3586     // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n");\r
3587     // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n");\r
3588     // buf.append("symbols: '" + symbols + "'");\r
3589     // }\r
3590 \r
3591     /**\r
3592      * Overrides hashCode.\r
3593      * @stable ICU 2.0\r
3594      */\r
3595     public int hashCode() {\r
3596         return super.hashCode() * 37 + positivePrefix.hashCode();\r
3597         // just enough fields for a reasonable distribution\r
3598     }\r
3599 \r
3600     /**\r
3601      * Synthesizes a pattern string that represents the current state of this Format\r
3602      * object.\r
3603      *\r
3604      * @see #applyPattern\r
3605      * @stable ICU 2.0\r
3606      */\r
3607     public String toPattern() {\r
3608         if (style == NumberFormat.PLURALCURRENCYSTYLE) {\r
3609             // the prefix or suffix pattern might not be defined yet, so they can not be\r
3610             // synthesized, instead, get them directly.  but it might not be the actual\r
3611             // pattern used in formatting.  the actual pattern used in formatting depends\r
3612             // on the formatted number's plural count.\r
3613             return formatPattern;\r
3614         }\r
3615         return toPattern(false);\r
3616     }\r
3617 \r
3618     /**\r
3619      * Synthesizes a localized pattern string that represents the current state of this\r
3620      * Format object.\r
3621      *\r
3622      * @see #applyPattern\r
3623      * @stable ICU 2.0\r
3624      */\r
3625     public String toLocalizedPattern() {\r
3626         if (style == NumberFormat.PLURALCURRENCYSTYLE) {\r
3627             return formatPattern;\r
3628         }\r
3629         return toPattern(true);\r
3630     }\r
3631 \r
3632     /**\r
3633      * Expands the affix pattern strings into the expanded affix strings. If any affix\r
3634      * pattern string is null, do not expand it. This method should be called any time the\r
3635      * symbols or the affix patterns change in order to keep the expanded affix strings up\r
3636      * to date. This method also will be called before formatting if format currency\r
3637      * plural names, since the plural name is not a static one, it is based on the\r
3638      * currency plural count, the affix will be known only after the currency plural count\r
3639      * is know. In which case, the parameter 'pluralCount' will be a non-null currency\r
3640      * plural count. In all other cases, the 'pluralCount' is null, which means it is not\r
3641      * needed.\r
3642      */\r
3643     // Bug 4212072 [Richard/GCL]\r
3644     private void expandAffixes(String pluralCount) {\r
3645         // expandAffix() will set currencyChoice to a non-null value if\r
3646         // appropriate AND if it is null.\r
3647         currencyChoice = null;\r
3648 \r
3649         // Reuse one StringBuffer for better performance\r
3650         StringBuffer buffer = new StringBuffer();\r
3651         if (posPrefixPattern != null) {\r
3652             expandAffix(posPrefixPattern, pluralCount, buffer, false);\r
3653             positivePrefix = buffer.toString();\r
3654         }\r
3655         if (posSuffixPattern != null) {\r
3656             expandAffix(posSuffixPattern, pluralCount, buffer, false);\r
3657             positiveSuffix = buffer.toString();\r
3658         }\r
3659         if (negPrefixPattern != null) {\r
3660             expandAffix(negPrefixPattern, pluralCount, buffer, false);\r
3661             negativePrefix = buffer.toString();\r
3662         }\r
3663         if (negSuffixPattern != null) {\r
3664             expandAffix(negSuffixPattern, pluralCount, buffer, false);\r
3665             negativeSuffix = buffer.toString();\r
3666         }\r
3667     }\r
3668 \r
3669     /**\r
3670      * Expands an affix pattern into an affix string. All characters in the pattern are\r
3671      * literal unless bracketed by QUOTEs. The following characters outside QUOTE are\r
3672      * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and\r
3673      * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international\r
3674      * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural\r
3675      * long names, such as "US Dollars". Any other character outside QUOTE represents\r
3676      * itself. Quoted text must be well-formed.\r
3677      *\r
3678      * This method is used in two distinct ways. First, it is used to expand the stored\r
3679      * affix patterns into actual affixes. For this usage, doFormat must be false. Second,\r
3680      * it is used to expand the stored affix patterns given a specific number (doFormat ==\r
3681      * true), for those rare cases in which a currency format references a ChoiceFormat\r
3682      * (e.g., en_IN display name for INR). The number itself is taken from digitList.\r
3683      *\r
3684      * When used in the first way, this method has a side effect: It sets currencyChoice\r
3685      * to a ChoiceFormat object, if the currency's display name in this locale is a\r
3686      * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to\r
3687      * start with.\r
3688      *\r
3689      * @param pattern the non-null, possibly empty pattern\r
3690      * @param pluralCount the plural count. It is only used for currency plural format. In\r
3691      * which case, it is the plural count of the currency amount. For example, in en_US,\r
3692      * it is the singular "one", or the plural "other". For all other cases, it is null,\r
3693      * and is not being used.\r
3694      * @param buffer a scratch StringBuffer; its contents will be lost\r
3695      * @param doFormat if false, then the pattern will be expanded, and if a currency\r
3696      * symbol is encountered that expands to a ChoiceFormat, the currencyChoice member\r
3697      * variable will be initialized if it is null. If doFormat is true, then it is assumed\r
3698      * that the currencyChoice has been created, and it will be used to format the value\r
3699      * in digitList.\r
3700      */\r
3701     // Bug 4212072 [Richard/GCL]\r
3702     private void expandAffix(String pattern, String pluralCount, StringBuffer buffer,\r
3703                              boolean doFormat) {\r
3704         buffer.setLength(0);\r
3705         for (int i = 0; i < pattern.length();) {\r
3706             char c = pattern.charAt(i++);\r
3707             if (c == QUOTE) {\r
3708                 for (;;) {\r
3709                     int j = pattern.indexOf(QUOTE, i);\r
3710                     if (j == i) {\r
3711                         buffer.append(QUOTE);\r
3712                         i = j + 1;\r
3713                         break;\r
3714                     } else if (j > i) {\r
3715                         buffer.append(pattern.substring(i, j));\r
3716                         i = j + 1;\r
3717                         if (i < pattern.length() && pattern.charAt(i) == QUOTE) {\r
3718                             buffer.append(QUOTE);\r
3719                             ++i;\r
3720                             // loop again\r
3721                         } else {\r
3722                             break;\r
3723                         }\r
3724                     } else {\r
3725                         // Unterminated quote; should be caught by apply\r
3726                         // pattern.\r
3727                         throw new RuntimeException();\r
3728                     }\r
3729                 }\r
3730                 continue;\r
3731             }\r
3732 \r
3733             switch (c) {\r
3734             case CURRENCY_SIGN:\r
3735                 // As of ICU 2.2 we use the currency object, and ignore the currency\r
3736                 // symbols in the DFS, unless we have a null currency object. This occurs\r
3737                 // if resurrecting a pre-2.2 object or if the user sets a custom DFS.\r
3738                 boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN;\r
3739                 boolean plural = false;\r
3740                 if (intl) {\r
3741                     ++i;\r
3742                     if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) {\r
3743                         plural = true;\r
3744                         intl = false;\r
3745                         ++i;\r
3746                     }\r
3747                 }\r
3748                 String s = null;\r
3749                 Currency currency = getCurrency();\r
3750                 if (currency != null) {\r
3751                     // plural name is only needed when pluralCount != null, which means\r
3752                     // when formatting currency plural names.  For other cases,\r
3753                     // pluralCount == null, and plural names are not needed.\r
3754                     if (plural && pluralCount != null) {\r
3755                         boolean isChoiceFormat[] = new boolean[1];\r
3756                         s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,\r
3757                                              pluralCount, isChoiceFormat);\r
3758                     } else if (!intl) {\r
3759                         boolean isChoiceFormat[] = new boolean[1];\r
3760                         s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME,\r
3761                                              isChoiceFormat);\r
3762                         if (isChoiceFormat[0]) {\r
3763                             // Two modes here: If doFormat is false, we set up\r
3764                             // currencyChoice. If doFormat is true, we use the previously\r
3765                             // created currencyChoice to format the value in digitList.\r
3766                             if (!doFormat) {\r
3767                                 // If the currency is handled by a ChoiceFormat, then\r
3768                                 // we're not going to use the expanded\r
3769                                 // patterns. Instantiate the ChoiceFormat and return.\r
3770                                 if (currencyChoice == null) {\r
3771                                     currencyChoice = new ChoiceFormat(s);\r
3772                                 }\r
3773                                 // We could almost return null or "" here, since the\r
3774                                 // expanded affixes are almost not used at all in this\r
3775                                 // situation. However, one method -- toPattern() -- still\r
3776                                 // does use the expanded affixes, in order to set up a\r
3777                                 // padding pattern. We use the CURRENCY_SIGN as a\r
3778                                 // placeholder.\r
3779                                 s = String.valueOf(CURRENCY_SIGN);\r
3780                             } else {\r
3781                                 FieldPosition pos = new FieldPosition(0); // ignored\r
3782                                 currencyChoice.format(digitList.getDouble(), buffer, pos);\r
3783                                 continue;\r
3784                             }\r
3785                         }\r
3786                     } else {\r
3787                         s = currency.getCurrencyCode();\r
3788                     }\r
3789                 } else {\r
3790                     s = intl ? symbols.getInternationalCurrencySymbol() :\r
3791                         symbols.getCurrencySymbol();\r
3792                 }\r
3793                 buffer.append(s);\r
3794                 continue;\r
3795             case PATTERN_PERCENT:\r
3796                 c = symbols.getPercent();\r
3797                 break;\r
3798             case PATTERN_PER_MILLE:\r
3799                 c = symbols.getPerMill();\r
3800                 break;\r
3801             case PATTERN_MINUS:\r
3802                 c = symbols.getMinusSign();\r
3803                 break;\r
3804             }\r
3805             buffer.append(c);\r
3806         }\r
3807     }\r
3808 \r
3809     /**\r
3810      * Append an affix to the given StringBuffer.\r
3811      *\r
3812      * @param buf\r
3813      *            buffer to append to\r
3814      * @param isNegative\r
3815      * @param isPrefix\r
3816      */\r
3817     private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,\r
3818                             boolean parseAttr) {\r
3819         if (currencyChoice != null) {\r
3820             String affixPat = null;\r
3821             if (isPrefix) {\r
3822                 affixPat = isNegative ? negPrefixPattern : posPrefixPattern;\r
3823             } else {\r
3824                 affixPat = isNegative ? negSuffixPattern : posSuffixPattern;\r
3825             }\r
3826             StringBuffer affixBuf = new StringBuffer();\r
3827             expandAffix(affixPat, null, affixBuf, true);\r
3828             buf.append(affixBuf);\r
3829             return affixBuf.length();\r
3830         }\r
3831 \r
3832         String affix = null;\r
3833         if (isPrefix) {\r
3834             affix = isNegative ? negativePrefix : positivePrefix;\r
3835         } else {\r
3836             affix = isNegative ? negativeSuffix : positiveSuffix;\r
3837         }\r
3838         // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix\r
3839         if (parseAttr) {\r
3840             int offset = affix.indexOf(symbols.getCurrencySymbol());\r
3841             if (-1 == offset) {\r
3842                 offset = affix.indexOf(symbols.getPercent());\r
3843                 if (-1 == offset) {\r
3844                     offset = 0;\r
3845                 }\r
3846             }\r
3847             formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length());\r
3848         }\r
3849         buf.append(affix);\r
3850         return affix.length();\r
3851     }\r
3852 \r
3853     /**\r
3854      * [Spark/CDL] This is a newly added method, used to add attributes for prefix and\r
3855      * suffix.\r
3856      */\r
3857     private void formatAffix2Attribute(String affix, int begin, int end) {\r
3858         // [Spark/CDL] It is the invoker's responsibility to ensure that, before the\r
3859         // invocation of this method, attributes is not null.  if( attributes == null )\r
3860         // return;\r
3861         if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {\r
3862             addAttribute(Field.CURRENCY, begin, end);\r
3863         } else if (affix.indexOf(symbols.getMinusSign()) > -1) {\r
3864             addAttribute(Field.SIGN, begin, end);\r
3865         } else if (affix.indexOf(symbols.getPercent()) > -1) {\r
3866             addAttribute(Field.PERCENT, begin, end);\r
3867         } else if (affix.indexOf(symbols.getPerMill()) > -1) {\r
3868             addAttribute(Field.PERMILLE, begin, end);\r
3869         }\r
3870     }\r
3871 \r
3872     /**\r
3873      * [Spark/CDL] Use this method to add attribute.\r
3874      */\r
3875     private void addAttribute(Field field, int begin, int end) {\r
3876         FieldPosition pos = new FieldPosition(field);\r
3877         pos.setBeginIndex(begin);\r
3878         pos.setEndIndex(end);\r
3879         attributes.add(pos);\r
3880     }\r
3881 \r
3882     /**\r
3883      * Formats the object to an attributed string, and return the corresponding iterator.\r
3884      *\r
3885      * @stable ICU 3.6\r
3886      */\r
3887     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {\r
3888         if (!(obj instanceof Number))\r
3889             throw new IllegalArgumentException();\r
3890         Number number = (Number) obj;\r
3891         StringBuffer text = null;\r
3892         attributes.clear();\r
3893         if (obj instanceof BigInteger) {\r
3894             text = format((BigInteger) number, new StringBuffer(), new FieldPosition(0), true);\r
3895         } else if (obj instanceof java.math.BigDecimal) {\r
3896             text = format((java.math.BigDecimal) number, new StringBuffer(), new FieldPosition(0)\r
3897                           , true);\r
3898         } else if (obj instanceof Double) {\r
3899             text = format(number.doubleValue(), new StringBuffer(), new FieldPosition(0), true);\r
3900         } else if (obj instanceof Integer || obj instanceof Long) {\r
3901             text = format(number.longValue(), new StringBuffer(), new FieldPosition(0), true);\r
3902         }\r
3903 \r
3904         AttributedString as = new AttributedString(text.toString());\r
3905 \r
3906         // add NumberFormat field attributes to the AttributedString\r
3907         for (int i = 0; i < attributes.size(); i++) {\r
3908             FieldPosition pos = attributes.get(i);\r
3909             Format.Field attribute = pos.getFieldAttribute();\r
3910             as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());\r
3911         }\r
3912 \r
3913         // return the CharacterIterator from AttributedString\r
3914         return as.getIterator();\r
3915     }\r
3916 \r
3917     /**\r
3918      * Appends an affix pattern to the given StringBuffer. Localize unquoted specials.\r
3919      */\r
3920     private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,\r
3921                                     boolean localized) {\r
3922         String affixPat = null;\r
3923         if (isPrefix) {\r
3924             affixPat = isNegative ? negPrefixPattern : posPrefixPattern;\r
3925         } else {\r
3926             affixPat = isNegative ? negSuffixPattern : posSuffixPattern;\r
3927         }\r
3928 \r
3929         // When there is a null affix pattern, we use the affix itself.\r
3930         if (affixPat == null) {\r
3931             String affix = null;\r
3932             if (isPrefix) {\r
3933                 affix = isNegative ? negativePrefix : positivePrefix;\r
3934             } else {\r
3935                 affix = isNegative ? negativeSuffix : positiveSuffix;\r
3936             }\r
3937             // Do this crudely for now: Wrap everything in quotes.\r
3938             buffer.append(QUOTE);\r
3939             for (int i = 0; i < affix.length(); ++i) {\r
3940                 char ch = affix.charAt(i);\r
3941                 if (ch == QUOTE) {\r
3942                     buffer.append(ch);\r
3943                 }\r
3944                 buffer.append(ch);\r
3945             }\r
3946             buffer.append(QUOTE);\r
3947             return;\r
3948         }\r
3949 \r
3950         if (!localized) {\r
3951             buffer.append(affixPat);\r
3952         } else {\r
3953             int i, j;\r
3954             for (i = 0; i < affixPat.length(); ++i) {\r
3955                 char ch = affixPat.charAt(i);\r
3956                 switch (ch) {\r
3957                 case QUOTE:\r
3958                     j = affixPat.indexOf(QUOTE, i + 1);\r
3959                     if (j < 0) {\r
3960                         throw new IllegalArgumentException("Malformed affix pattern: " + affixPat);\r
3961                     }\r
3962                     buffer.append(affixPat.substring(i, j + 1));\r
3963                     i = j;\r
3964                     continue;\r
3965                 case PATTERN_PER_MILLE:\r
3966                     ch = symbols.getPerMill();\r
3967                     break;\r
3968                 case PATTERN_PERCENT:\r
3969                     ch = symbols.getPercent();\r
3970                     break;\r
3971                 case PATTERN_MINUS:\r
3972                     ch = symbols.getMinusSign();\r
3973                     break;\r
3974                 }\r
3975                 // check if char is same as any other symbol\r
3976                 if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) {\r
3977                     buffer.append(QUOTE);\r
3978                     buffer.append(ch);\r
3979                     buffer.append(QUOTE);\r
3980                 } else {\r
3981                     buffer.append(ch);\r
3982                 }\r
3983             }\r
3984         }\r
3985     }\r
3986 \r
3987     /**\r
3988      * Does the real work of generating a pattern.\r
3989      */\r
3990     private String toPattern(boolean localized) {\r
3991         StringBuffer result = new StringBuffer();\r
3992         char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT;\r
3993         char digit = localized ? symbols.getDigit() : PATTERN_DIGIT;\r
3994         char sigDigit = 0;\r
3995         boolean useSigDig = areSignificantDigitsUsed();\r
3996         if (useSigDig) {\r
3997             sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT;\r
3998         }\r
3999         char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR;\r
4000         int i;\r
4001         int roundingDecimalPos = 0; // Pos of decimal in roundingDigits\r
4002         String roundingDigits = null;\r
4003         int padPos = (formatWidth > 0) ? padPosition : -1;\r
4004         String padSpec = (formatWidth > 0)\r
4005             ? new StringBuffer(2).append(localized\r
4006                                          ? symbols.getPadEscape()\r
4007                                          : PATTERN_PAD_ESCAPE).append(pad).toString()\r
4008             : null;\r
4009         if (roundingIncrementICU != null) {\r
4010             i = roundingIncrementICU.scale();\r
4011             roundingDigits = roundingIncrementICU.movePointRight(i).toString();\r
4012             roundingDecimalPos = roundingDigits.length() - i;\r
4013         }\r
4014         for (int part = 0; part < 2; ++part) {\r
4015             // variable not used int partStart = result.length();\r
4016             if (padPos == PAD_BEFORE_PREFIX) {\r
4017                 result.append(padSpec);\r
4018             }\r
4019 \r
4020             // Use original symbols read from resources in pattern eg. use "\u00A4"\r
4021             // instead of "$" in Locale.US [Richard/GCL]\r
4022             appendAffixPattern(result, part != 0, true, localized);\r
4023             if (padPos == PAD_AFTER_PREFIX) {\r
4024                 result.append(padSpec);\r
4025             }\r
4026             int sub0Start = result.length();\r
4027             int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0;\r
4028             if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) {\r
4029                 g += groupingSize2;\r
4030             }\r
4031             int maxDig = 0, minDig = 0, maxSigDig = 0;\r
4032             if (useSigDig) {\r
4033                 minDig = getMinimumSignificantDigits();\r
4034                 maxDig = maxSigDig = getMaximumSignificantDigits();\r
4035             } else {\r
4036                 minDig = getMinimumIntegerDigits();\r
4037                 maxDig = getMaximumIntegerDigits();\r
4038             }\r
4039             if (useExponentialNotation) {\r
4040                 if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) {\r
4041                     maxDig = 1;\r
4042                 }\r
4043             } else if (useSigDig) {\r
4044                 maxDig = Math.max(maxDig, g + 1);\r
4045             } else {\r
4046                 maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1;\r
4047             }\r
4048             for (i = maxDig; i > 0; --i) {\r
4049                 if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) {\r
4050                     result.append(group);\r
4051                 }\r
4052                 if (useSigDig) {\r
4053                     // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos,\r
4054                     // count from the right) Use # if pos > maxSigDig or 1 <= pos <=\r
4055                     // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <=\r
4056                     // maxSigDig\r
4057                     result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit);\r
4058                 } else {\r
4059                     if (roundingDigits != null) {\r
4060                         int pos = roundingDecimalPos - i;\r
4061                         if (pos >= 0 && pos < roundingDigits.length()) {\r
4062                             result.append((char) (roundingDigits.charAt(pos) - '0' + zero));\r
4063                             continue;\r
4064                         }\r
4065                     }\r
4066                     result.append(i <= minDig ? zero : digit);\r
4067                 }\r
4068             }\r
4069             if (!useSigDig) {\r
4070                 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) {\r
4071                     result.append(localized ? symbols.getDecimalSeparator() :\r
4072                                   PATTERN_DECIMAL_SEPARATOR);\r
4073                 }\r
4074                 int pos = roundingDecimalPos;\r
4075                 for (i = 0; i < getMaximumFractionDigits(); ++i) {\r
4076                     if (roundingDigits != null && pos < roundingDigits.length()) {\r
4077                         result.append(pos < 0 ? zero :\r
4078                                       (char) (roundingDigits.charAt(pos) - '0' + zero));\r
4079                         ++pos;\r
4080                         continue;\r
4081                     }\r
4082                     result.append(i < getMinimumFractionDigits() ? zero : digit);\r
4083                 }\r
4084             }\r
4085             if (useExponentialNotation) {\r
4086                 if (localized) {\r
4087                     result.append(symbols.getExponentSeparator());\r
4088                 } else {\r
4089                     result.append(PATTERN_EXPONENT);\r
4090                 }\r
4091                 if (exponentSignAlwaysShown) {\r
4092                     result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN);\r
4093                 }\r
4094                 for (i = 0; i < minExponentDigits; ++i) {\r
4095                     result.append(zero);\r
4096                 }\r
4097             }\r
4098             if (padSpec != null && !useExponentialNotation) {\r
4099                 int add = formatWidth\r
4100                         - result.length()\r
4101                         + sub0Start\r
4102                         - ((part == 0)\r
4103                            ? positivePrefix.length() + positiveSuffix.length()\r
4104                            : negativePrefix.length() + negativeSuffix.length());\r
4105                 while (add > 0) {\r
4106                     result.insert(sub0Start, digit);\r
4107                     ++maxDig;\r
4108                     --add;\r
4109                     // Only add a grouping separator if we have at least 2 additional\r
4110                     // characters to be added, so we don't end up with ",###".\r
4111                     if (add > 1 && isGroupingPosition(maxDig)) {\r
4112                         result.insert(sub0Start, group);\r
4113                         --add;\r
4114                     }\r
4115                 }\r
4116             }\r
4117             if (padPos == PAD_BEFORE_SUFFIX) {\r
4118                 result.append(padSpec);\r
4119             }\r
4120             // Use original symbols read from resources in pattern eg. use "\u00A4"\r
4121             // instead of "$" in Locale.US [Richard/GCL]\r
4122             appendAffixPattern(result, part != 0, false, localized);\r
4123             if (padPos == PAD_AFTER_SUFFIX) {\r
4124                 result.append(padSpec);\r
4125             }\r
4126             if (part == 0) {\r
4127                 if (negativeSuffix.equals(positiveSuffix) &&\r
4128                     negativePrefix.equals(PATTERN_MINUS + positivePrefix)) {\r
4129                     break;\r
4130                 } else {\r
4131                     result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);\r
4132                 }\r
4133             }\r
4134         }\r
4135         return result.toString();\r
4136     }\r
4137 \r
4138     /**\r
4139      * Applies the given pattern to this Format object. A pattern is a short-hand\r
4140      * specification for the various formatting properties. These properties can also be\r
4141      * changed individually through the various setter methods.\r
4142      *\r
4143      * <p>There is no limit to integer digits are set by this routine, since that is the\r
4144      * typical end-user desire; use setMaximumInteger if you want to set a real value. For\r
4145      * negative numbers, use a second pattern, separated by a semicolon\r
4146      *\r
4147      * <p>Example "#,#00.0#" -> 1,234.56\r
4148      *\r
4149      * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2\r
4150      * fraction digits.\r
4151      *\r
4152      * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses.\r
4153      *\r
4154      * <p>In negative patterns, the minimum and maximum counts are ignored; these are\r
4155      * presumed to be set in the positive pattern.\r
4156      *\r
4157      * @stable ICU 2.0\r
4158      */\r
4159     public void applyPattern(String pattern) {\r
4160         applyPattern(pattern, false);\r
4161     }\r
4162 \r
4163     /**\r
4164      * Applies the given pattern to this Format object. The pattern is assumed to be in a\r
4165      * localized notation. A pattern is a short-hand specification for the various\r
4166      * formatting properties. These properties can also be changed individually through\r
4167      * the various setter methods.\r
4168      *\r
4169      * <p>There is no limit to integer digits are set by this routine, since that is the\r
4170      * typical end-user desire; use setMaximumInteger if you want to set a real value. For\r
4171      * negative numbers, use a second pattern, separated by a semicolon\r
4172      *\r
4173      * <p>Example "#,#00.0#" -> 1,234.56\r
4174      *\r
4175      * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2\r
4176      * fraction digits.\r
4177      *\r
4178      * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.\r
4179      *\r
4180      * <p>In negative patterns, the minimum and maximum counts are ignored; these are\r
4181      * presumed to be set in the positive pattern.\r
4182      *\r
4183      * @stable ICU 2.0\r
4184      */\r
4185     public void applyLocalizedPattern(String pattern) {\r
4186         applyPattern(pattern, true);\r
4187     }\r
4188 \r
4189     /**\r
4190      * Does the real work of applying a pattern.\r
4191      */\r
4192     private void applyPattern(String pattern, boolean localized) {\r
4193         applyPatternWithoutExpandAffix(pattern, localized);\r
4194         expandAffixAdjustWidth(null);\r
4195     }\r
4196 \r
4197     private void expandAffixAdjustWidth(String pluralCount) {\r
4198         // Bug 4212072 Update the affix strings according to symbols in order to keep the\r
4199         // affix strings up to date.  [Richard/GCL]\r
4200         expandAffixes(pluralCount);\r
4201 \r
4202         // Now that we have the actual prefix and suffix, fix up formatWidth\r
4203         if (formatWidth > 0) {\r
4204             formatWidth += positivePrefix.length() + positiveSuffix.length();\r
4205         }\r
4206     }\r
4207 \r
4208     private void applyPatternWithoutExpandAffix(String pattern, boolean localized) {\r
4209         char zeroDigit = PATTERN_ZERO_DIGIT; // '0'\r
4210         char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@'\r
4211         char groupingSeparator = PATTERN_GROUPING_SEPARATOR;\r
4212         char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;\r
4213         char percent = PATTERN_PERCENT;\r
4214         char perMill = PATTERN_PER_MILLE;\r
4215         char digit = PATTERN_DIGIT; // '#'\r
4216         char separator = PATTERN_SEPARATOR;\r
4217         String exponent = String.valueOf(PATTERN_EXPONENT);\r
4218         char plus = PATTERN_PLUS_SIGN;\r
4219         char padEscape = PATTERN_PAD_ESCAPE;\r
4220         char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL]\r
4221         if (localized) {\r
4222             zeroDigit = symbols.getZeroDigit();\r
4223             sigDigit = symbols.getSignificantDigit();\r
4224             groupingSeparator = symbols.getGroupingSeparator();\r
4225             decimalSeparator = symbols.getDecimalSeparator();\r
4226             percent = symbols.getPercent();\r
4227             perMill = symbols.getPerMill();\r
4228             digit = symbols.getDigit();\r
4229             separator = symbols.getPatternSeparator();\r
4230             exponent = symbols.getExponentSeparator();\r
4231             plus = symbols.getPlusSign();\r
4232             padEscape = symbols.getPadEscape();\r
4233             minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL]\r
4234         }\r
4235         char nineDigit = (char) (zeroDigit + 9);\r
4236 \r
4237         boolean gotNegative = false;\r
4238 \r
4239         int pos = 0;\r
4240         // Part 0 is the positive pattern. Part 1, if present, is the negative\r
4241         // pattern.\r
4242         for (int part = 0; part < 2 && pos < pattern.length(); ++part) {\r
4243             // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix,\r
4244             // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and\r
4245             // suffix, and consists of pattern characters. In the prefix and suffix,\r
4246             // percent, permille, and currency symbols are recognized and translated.\r
4247             int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0;\r
4248 \r
4249             // It's important that we don't change any fields of this object\r
4250             // prematurely. We set the following variables for the multiplier, grouping,\r
4251             // etc., and then only change the actual object fields if everything parses\r
4252             // correctly. This also lets us register the data from part 0 and ignore the\r
4253             // part 1, except for the prefix and suffix.\r
4254             StringBuilder prefix = new StringBuilder();\r
4255             StringBuilder suffix = new StringBuilder();\r
4256             int decimalPos = -1;\r
4257             int multpl = 1;\r
4258             int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0;\r
4259             byte groupingCount = -1;\r
4260             byte groupingCount2 = -1;\r
4261             int padPos = -1;\r
4262             char padChar = 0;\r
4263             int incrementPos = -1;\r
4264             long incrementVal = 0;\r
4265             byte expDigits = -1;\r
4266             boolean expSignAlways = false;\r
4267 \r
4268             // The affix is either the prefix or the suffix.\r
4269             StringBuilder affix = prefix;\r
4270 \r
4271             int start = pos;\r
4272 \r
4273             PARTLOOP: for (; pos < pattern.length(); ++pos) {\r
4274                 char ch = pattern.charAt(pos);\r
4275                 switch (subpart) {\r
4276                 case 0: // Pattern proper subpart (between prefix & suffix)\r
4277                     // Process the digits, decimal, and grouping characters. We record\r
4278                     // five pieces of information. We expect the digits to occur in the\r
4279                     // pattern ####00.00####, and we record the number of left digits,\r
4280                     // zero (central) digits, and right digits. The position of the last\r
4281                     // grouping character is recorded (should be somewhere within the\r
4282                     // first two blocks of characters), as is the position of the decimal\r
4283                     // point, if any (should be in the zero digits). If there is no\r
4284                     // decimal point, then there should be no right digits.\r
4285                     if (ch == digit) {\r
4286                         if (zeroDigitCount > 0 || sigDigitCount > 0) {\r
4287                             ++digitRightCount;\r
4288                         } else {\r
4289                             ++digitLeftCount;\r
4290                         }\r
4291                         if (groupingCount >= 0 && decimalPos < 0) {\r
4292                             ++groupingCount;\r
4293                         }\r
4294                     } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {\r
4295                         if (digitRightCount > 0) {\r
4296                             patternError("Unexpected '" + ch + '\'', pattern);\r
4297                         }\r
4298                         if (ch == sigDigit) {\r
4299                             ++sigDigitCount;\r
4300                         } else {\r
4301                             ++zeroDigitCount;\r
4302                             if (ch != zeroDigit) {\r
4303                                 int p = digitLeftCount + zeroDigitCount + digitRightCount;\r
4304                                 if (incrementPos >= 0) {\r
4305                                     while (incrementPos < p) {\r
4306                                         incrementVal *= 10;\r
4307                                         ++incrementPos;\r
4308                                     }\r
4309                                 } else {\r
4310                                     incrementPos = p;\r
4311                                 }\r
4312                                 incrementVal += ch - zeroDigit;\r
4313                             }\r
4314                         }\r
4315                         if (groupingCount >= 0 && decimalPos < 0) {\r
4316                             ++groupingCount;\r
4317                         }\r
4318                     } else if (ch == groupingSeparator) {\r
4319                         // Bug 4212072 process the Localized pattern like\r
4320                         // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator\r
4321                         // == QUOTE) [Richard/GCL]\r
4322                         if (ch == QUOTE && (pos + 1) < pattern.length()) {\r
4323                             char after = pattern.charAt(pos + 1);\r
4324                             if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) {\r
4325                                 // A quote outside quotes indicates either the opening\r
4326                                 // quote or two quotes, which is a quote literal. That is,\r
4327                                 // we have the first quote in 'do' or o''clock.\r
4328                                 if (after == QUOTE) {\r
4329                                     ++pos;\r
4330                                     // Fall through to append(ch)\r
4331                                 } else {\r
4332                                     if (groupingCount < 0) {\r
4333                                         subpart = 3; // quoted prefix subpart\r
4334                                     } else {\r
4335                                         // Transition to suffix subpart\r
4336                                         subpart = 2; // suffix subpart\r
4337                                         affix = suffix;\r
4338                                         sub0Limit = pos--;\r
4339                                     }\r
4340                                     continue;\r
4341                                 }\r
4342                             }\r
4343                         }\r
4344 \r
4345                         if (decimalPos >= 0) {\r
4346                             patternError("Grouping separator after decimal", pattern);\r
4347                         }\r
4348                         groupingCount2 = groupingCount;\r
4349                         groupingCount = 0;\r
4350                     } else if (ch == decimalSeparator) {\r
4351                         if (decimalPos >= 0) {\r
4352                             patternError("Multiple decimal separators", pattern);\r
4353                         }\r
4354                         // Intentionally incorporate the digitRightCount, even though it\r
4355                         // is illegal for this to be > 0 at this point. We check pattern\r
4356                         // syntax below.\r
4357                         decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;\r
4358                     } else {\r
4359                         if (pattern.regionMatches(pos, exponent, 0, exponent.length())) {\r
4360                             if (expDigits >= 0) {\r
4361                                 patternError("Multiple exponential symbols", pattern);\r
4362                             }\r
4363                             if (groupingCount >= 0) {\r
4364                                 patternError("Grouping separator in exponential", pattern);\r
4365                             }\r
4366                             pos += exponent.length();\r
4367                             // Check for positive prefix\r
4368                             if (pos < pattern.length() && pattern.charAt(pos) == plus) {\r
4369                                 expSignAlways = true;\r
4370                                 ++pos;\r
4371                             }\r
4372                             // Use lookahead to parse out the exponential part of the\r
4373                             // pattern, then jump into suffix subpart.\r
4374                             expDigits = 0;\r
4375                             while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) {\r
4376                                 ++expDigits;\r
4377                                 ++pos;\r
4378                             }\r
4379 \r
4380                             // 1. Require at least one mantissa pattern digit\r
4381                             // 2. Disallow "#+ @" in mantissa\r
4382                             // 3. Require at least one exponent pattern digit\r
4383                             if (((digitLeftCount + zeroDigitCount) < 1 &&\r
4384                                  (sigDigitCount + digitRightCount) < 1)\r
4385                                 || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) {\r
4386                                 patternError("Malformed exponential", pattern);\r
4387                             }\r
4388                         }\r
4389                         // Transition to suffix subpart\r
4390                         subpart = 2; // suffix subpart\r
4391                         affix = suffix;\r
4392                         sub0Limit = pos--; // backup: for() will increment\r
4393                         continue;\r
4394                     }\r
4395                     break;\r
4396                 case 1: // Prefix subpart\r
4397                 case 2: // Suffix subpart\r
4398                     // Process the prefix / suffix characters Process unquoted characters\r
4399                     // seen in prefix or suffix subpart.\r
4400 \r
4401                     // Several syntax characters implicitly begins the next subpart if we\r
4402                     // are in the prefix; otherwise they are illegal if unquoted.\r
4403                     if (ch == digit || ch == groupingSeparator || ch == decimalSeparator\r
4404                             || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) {\r
4405                         // Any of these characters implicitly begins the\r
4406                         // next subpart if we are in the prefix\r
4407                         if (subpart == 1) { // prefix subpart\r
4408                             subpart = 0; // pattern proper subpart\r
4409                             sub0Start = pos--; // Reprocess this character\r
4410                             continue;\r
4411                         } else if (ch == QUOTE) {\r
4412                             // Bug 4212072 process the Localized pattern like\r
4413                             // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH",\r
4414                             // groupingSeparator == QUOTE) [Richard/GCL]\r
4415 \r
4416                             // A quote outside quotes indicates either the opening quote\r
4417                             // or two quotes, which is a quote literal. That is, we have\r
4418                             // the first quote in 'do' or o''clock.\r
4419                             if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {\r
4420                                 ++pos;\r
4421                                 affix.append(ch);\r
4422                             } else {\r
4423                                 subpart += 2; // open quote\r
4424                             }\r
4425                             continue;\r
4426                         }\r
4427                         patternError("Unquoted special character '" + ch + '\'', pattern);\r
4428                     } else if (ch == CURRENCY_SIGN) {\r
4429                         // Use lookahead to determine if the currency sign is\r
4430                         // doubled or not.\r
4431                         boolean doubled = (pos + 1) < pattern.length() &&\r
4432                             pattern.charAt(pos + 1) == CURRENCY_SIGN;\r
4433 \r
4434                         // Bug 4212072 To meet the need of expandAffix(String,\r
4435                         // StirngBuffer) [Richard/GCL]\r
4436                         if (doubled) {\r
4437                             ++pos; // Skip over the doubled character\r
4438                             affix.append(ch); // append two: one here, one below\r
4439                             if ((pos + 1) < pattern.length() &&\r
4440                                 pattern.charAt(pos + 1) == CURRENCY_SIGN) {\r
4441                                 ++pos; // Skip over the tripled character\r
4442                                 affix.append(ch); // append again\r
4443                                 currencySignCount = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT;\r
4444                             } else {\r
4445                                 currencySignCount = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT;\r
4446                             }\r
4447                         } else {\r
4448                             currencySignCount = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT;\r
4449                         }\r
4450                         // Fall through to append(ch)\r
4451                     } else if (ch == QUOTE) {\r
4452                         // A quote outside quotes indicates either the opening quote or\r
4453                         // two quotes, which is a quote literal. That is, we have the\r
4454                         // first quote in 'do' or o''clock.\r
4455                         if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {\r
4456                             ++pos;\r
4457                             affix.append(ch); // append two: one here, one below\r
4458                         } else {\r
4459                             subpart += 2; // open quote\r
4460                         }\r
4461                         // Fall through to append(ch)\r
4462                     } else if (ch == separator) {\r
4463                         // Don't allow separators in the prefix, and don't allow\r
4464                         // separators in the second pattern (part == 1).\r
4465                         if (subpart == 1 || part == 1) {\r
4466                             patternError("Unquoted special character '" + ch + '\'', pattern);\r
4467                         }\r
4468                         sub2Limit = pos++;\r
4469                         break PARTLOOP; // Go to next part\r
4470                     } else if (ch == percent || ch == perMill) {\r
4471                         // Next handle characters which are appended directly.\r
4472                         if (multpl != 1) {\r
4473                             patternError("Too many percent/permille characters", pattern);\r
4474                         }\r
4475                         multpl = (ch == percent) ? 100 : 1000;\r
4476                         // Convert to non-localized pattern\r
4477                         ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE;\r
4478                         // Fall through to append(ch)\r
4479                     } else if (ch == minus) {\r
4480                         // Convert to non-localized pattern\r
4481                         ch = PATTERN_MINUS;\r
4482                         // Fall through to append(ch)\r
4483                     } else if (ch == padEscape) {\r
4484                         if (padPos >= 0) {\r
4485                             patternError("Multiple pad specifiers", pattern);\r
4486                         }\r
4487                         if ((pos + 1) == pattern.length()) {\r
4488                             patternError("Invalid pad specifier", pattern);\r
4489                         }\r
4490                         padPos = pos++; // Advance past pad char\r
4491                         padChar = pattern.charAt(pos);\r
4492                         continue;\r
4493                     }\r
4494                     affix.append(ch);\r
4495                     break;\r
4496                 case 3: // Prefix subpart, in quote\r
4497                 case 4: // Suffix subpart, in quote\r
4498                     // A quote within quotes indicates either the closing quote or two\r
4499                     // quotes, which is a quote literal. That is, we have the second quote\r
4500                     // in 'do' or 'don''t'.\r
4501                     if (ch == QUOTE) {\r
4502                         if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) {\r
4503                             ++pos;\r
4504                             affix.append(ch);\r
4505                         } else {\r
4506                             subpart -= 2; // close quote\r
4507                         }\r
4508                         // Fall through to append(ch)\r
4509                     }\r
4510                     // NOTE: In ICU 2.2 there was code here to parse quoted percent and\r
4511                     // permille characters _within quotes_ and give them special\r
4512                     // meaning. This is incorrect, since quoted characters are literals\r
4513                     // without special meaning.\r
4514                     affix.append(ch);\r
4515                     break;\r
4516                 }\r
4517             }\r
4518 \r
4519             if (subpart == 3 || subpart == 4) {\r
4520                 patternError("Unterminated quote", pattern);\r
4521             }\r
4522 \r
4523             if (sub0Limit == 0) {\r
4524                 sub0Limit = pattern.length();\r
4525             }\r
4526 \r
4527             if (sub2Limit == 0) {\r
4528                 sub2Limit = pattern.length();\r
4529             }\r
4530 \r
4531             // Handle patterns with no '0' pattern character. These patterns are legal,\r
4532             // but must be recodified to make sense. "##.###" -> "#0.###". ".###" ->\r
4533             // ".0##".\r
4534             //\r
4535             // We allow patterns of the form "####" to produce a zeroDigitCount of zero\r
4536             // (got that?); although this seems like it might make it possible for\r
4537             // format() to produce empty strings, format() checks for this condition and\r
4538             // outputs a zero digit in this situation. Having a zeroDigitCount of zero\r
4539             // yields a minimum integer digits of zero, which allows proper round-trip\r
4540             // patterns. We don't want "#" to become "#0" when toPattern() is called (even\r
4541             // though that's what it really is, semantically).\r
4542             if (zeroDigitCount == 0 && sigDigitCount == 0 &&\r
4543                 digitLeftCount > 0 && decimalPos >= 0) {\r
4544                 // Handle "###.###" and "###." and ".###"\r
4545                 int n = decimalPos;\r
4546                 if (n == 0)\r
4547                     ++n; // Handle ".###"\r
4548                 digitRightCount = digitLeftCount - n;\r
4549                 digitLeftCount = n - 1;\r
4550                 zeroDigitCount = 1;\r
4551             }\r
4552 \r
4553             // Do syntax checking on the digits, decimal points, and quotes.\r
4554             if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0)\r
4555                 || (decimalPos >= 0\r
4556                     && (sigDigitCount > 0\r
4557                         || decimalPos < digitLeftCount\r
4558                         || decimalPos > (digitLeftCount + zeroDigitCount)))\r
4559                 || groupingCount == 0\r
4560                 || groupingCount2 == 0\r
4561                 || (sigDigitCount > 0 && zeroDigitCount > 0)\r
4562                 || subpart > 2) { // subpart > 2 == unmatched quote\r
4563                 patternError("Malformed pattern", pattern);\r
4564             }\r
4565 \r
4566             // Make sure pad is at legal position before or after affix.\r
4567             if (padPos >= 0) {\r
4568                 if (padPos == start) {\r
4569                     padPos = PAD_BEFORE_PREFIX;\r
4570                 } else if (padPos + 2 == sub0Start) {\r
4571                     padPos = PAD_AFTER_PREFIX;\r
4572                 } else if (padPos == sub0Limit) {\r
4573                     padPos = PAD_BEFORE_SUFFIX;\r
4574                 } else if (padPos + 2 == sub2Limit) {\r
4575                     padPos = PAD_AFTER_SUFFIX;\r
4576                 } else {\r
4577                     patternError("Illegal pad position", pattern);\r
4578                 }\r
4579             }\r
4580 \r
4581             if (part == 0) {\r
4582                 // Set negative affixes temporarily to match the positive\r
4583                 // affixes. Fix this up later after processing both parts.\r
4584 \r
4585                 // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)\r
4586                 // [Richard/GCL]\r
4587                 posPrefixPattern = negPrefixPattern = prefix.toString();\r
4588                 posSuffixPattern = negSuffixPattern = suffix.toString();\r
4589 \r
4590                 useExponentialNotation = (expDigits >= 0);\r
4591                 if (useExponentialNotation) {\r
4592                     minExponentDigits = expDigits;\r
4593                     exponentSignAlwaysShown = expSignAlways;\r
4594                 }\r
4595                 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;\r
4596                 // The effectiveDecimalPos is the position the decimal is at or would be\r
4597                 // at if there is no decimal. Note that if decimalPos<0, then\r
4598                 // digitTotalCount == digitLeftCount + zeroDigitCount.\r
4599                 int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;\r
4600                 boolean useSigDig = (sigDigitCount > 0);\r
4601                 setSignificantDigitsUsed(useSigDig);\r
4602                 if (useSigDig) {\r
4603                     setMinimumSignificantDigits(sigDigitCount);\r
4604                     setMaximumSignificantDigits(sigDigitCount + digitRightCount);\r
4605                 } else {\r
4606                     int minInt = effectiveDecimalPos - digitLeftCount;\r
4607                     setMinimumIntegerDigits(minInt);\r
4608 \r
4609                     // Upper limit on integer and fraction digits for a Java double\r
4610                     // [Richard/GCL]\r
4611                     setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt :\r
4612                                             DOUBLE_INTEGER_DIGITS);\r
4613                     setMaximumFractionDigits(decimalPos >= 0 ?\r
4614                                              (digitTotalCount - decimalPos) : 0);\r
4615                     setMinimumFractionDigits(decimalPos >= 0 ?\r
4616                                              (digitLeftCount + zeroDigitCount - decimalPos) : 0);\r
4617                 }\r
4618                 setGroupingUsed(groupingCount > 0);\r
4619                 this.groupingSize = (groupingCount > 0) ? groupingCount : 0;\r
4620                 this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount)\r
4621                     ? groupingCount2 : 0;\r
4622                 this.multiplier = multpl;\r
4623                 setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);\r
4624                 if (padPos >= 0) {\r
4625                     padPosition = padPos;\r
4626                     formatWidth = sub0Limit - sub0Start; // to be fixed up below\r
4627                     pad = padChar;\r
4628                 } else {\r
4629                     formatWidth = 0;\r
4630                 }\r
4631                 if (incrementVal != 0) {\r
4632                     // BigDecimal scale cannot be negative (even though this makes perfect\r
4633                     // sense), so we need to handle this.\r
4634                     int scale = incrementPos - effectiveDecimalPos;\r
4635                     roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0);\r
4636                     if (scale < 0) {\r
4637                         roundingIncrementICU = roundingIncrementICU.movePointRight(-scale);\r
4638                     }\r
4639                     setRoundingDouble();\r
4640                     roundingMode = BigDecimal.ROUND_HALF_EVEN;\r
4641                 } else {\r
4642                     setRoundingIncrement((BigDecimal) null);\r
4643                 }\r
4644             } else {\r
4645                 // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer)\r
4646                 // [Richard/GCL]\r
4647                 negPrefixPattern = prefix.toString();\r
4648                 negSuffixPattern = suffix.toString();\r
4649                 gotNegative = true;\r
4650             }\r
4651         }\r
4652 \r
4653 \r
4654         // Bug 4140009 Process the empty pattern [Richard/GCL]\r
4655         if (pattern.length() == 0) {\r
4656             posPrefixPattern = posSuffixPattern = "";\r
4657             setMinimumIntegerDigits(0);\r
4658             setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);\r
4659             setMinimumFractionDigits(0);\r
4660             setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);\r
4661         }\r
4662 \r
4663         // If there was no negative pattern, or if the negative pattern is identical to\r
4664         // the positive pattern, then prepend the minus sign to the positive pattern to\r
4665         // form the negative pattern.\r
4666 \r
4667         // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]\r
4668 \r
4669         if (!gotNegative ||\r
4670             (negPrefixPattern.equals(posPrefixPattern)\r
4671              && negSuffixPattern.equals(posSuffixPattern))) {\r
4672             negSuffixPattern = posSuffixPattern;\r
4673             negPrefixPattern = PATTERN_MINUS + posPrefixPattern;\r
4674         }\r
4675         setLocale(null, null);\r
4676         // save the pattern\r
4677         formatPattern = pattern;\r
4678         // initialize currencyPluralInfo if needed\r
4679         if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT\r
4680             && currencyPluralInfo == null) {\r
4681             currencyPluralInfo = new CurrencyPluralInfo(symbols.getLocale());\r
4682         }\r
4683     }\r
4684 \r
4685     /**\r
4686      * Centralizes the setting of the roundingDouble and roundingDoubleReciprocal.\r
4687      */\r
4688     private void setRoundingDouble() {\r
4689         if (roundingIncrementICU == null) {\r
4690             roundingDouble = 0.0d;\r
4691             roundingDoubleReciprocal = 0.0d;\r
4692         } else {\r
4693             roundingDouble = roundingIncrementICU.doubleValue();\r
4694             setRoundingDoubleReciprocal(\r
4695                 BigDecimal.ONE.divide(roundingIncrementICU, BigDecimal.ROUND_HALF_EVEN)\r
4696                     .doubleValue());\r
4697         }\r
4698     }\r
4699 \r
4700     private void patternError(String msg, String pattern) {\r
4701         throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"');\r
4702     }\r
4703 \r
4704 \r
4705     // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits\r
4706     // for a Java double [Richard/GCL]\r
4707 \r
4708     /**\r
4709      * Sets the maximum number of digits allowed in the integer portion of a number. This\r
4710      * override limits the integer digit count to 309.\r
4711      *\r
4712      * @see NumberFormat#setMaximumIntegerDigits\r
4713      * @stable ICU 2.0\r
4714      */\r
4715     public void setMaximumIntegerDigits(int newValue) {\r
4716         super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));\r
4717     }\r
4718 \r
4719     /**\r
4720      * Sets the minimum number of digits allowed in the integer portion of a number. This\r
4721      * override limits the integer digit count to 309.\r
4722      *\r
4723      * @see NumberFormat#setMinimumIntegerDigits\r
4724      * @stable ICU 2.0\r
4725      */\r
4726     public void setMinimumIntegerDigits(int newValue) {\r
4727         super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));\r
4728     }\r
4729 \r
4730     /**\r
4731      * {@icu} Returns the minimum number of significant digits that will be\r
4732      * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}\r
4733      * returns true.\r
4734      *\r
4735      * @return the fewest significant digits that will be shown\r
4736      * @stable ICU 3.0\r
4737      */\r
4738     public int getMinimumSignificantDigits() {\r
4739         return minSignificantDigits;\r
4740     }\r
4741 \r
4742     /**\r
4743      * {@icu} Returns the maximum number of significant digits that will be\r
4744      * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()}\r
4745      * returns true.\r
4746      *\r
4747      * @return the most significant digits that will be shown\r
4748      * @stable ICU 3.0\r
4749      */\r
4750     public int getMaximumSignificantDigits() {\r
4751         return maxSignificantDigits;\r
4752     }\r
4753 \r
4754     /**\r
4755      * {@icu} Sets the minimum number of significant digits that will be displayed. If\r
4756      * <code>min</code> is less than one then it is set to one. If the maximum significant\r
4757      * digits count is less than <code>min</code>, then it is set to\r
4758      * <code>min</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}\r
4759      * returns true.\r
4760      *\r
4761      * @param min the fewest significant digits to be shown\r
4762      * @stable ICU 3.0\r
4763      */\r
4764     public void setMinimumSignificantDigits(int min) {\r
4765         if (min < 1) {\r
4766             min = 1;\r
4767         }\r
4768         // pin max sig dig to >= min\r
4769         int max = Math.max(maxSignificantDigits, min);\r
4770         minSignificantDigits = min;\r
4771         maxSignificantDigits = max;\r
4772     }\r
4773 \r
4774     /**\r
4775      * {@icu} Sets the maximum number of significant digits that will be displayed. If\r
4776      * <code>max</code> is less than one then it is set to one. If the minimum significant\r
4777      * digits count is greater than <code>max</code>, then it is set to\r
4778      * <code>max</code>. This value has no effect unless {@link #areSignificantDigitsUsed()}\r
4779      * returns true.\r
4780      *\r
4781      * @param max the most significant digits to be shown\r
4782      * @stable ICU 3.0\r
4783      */\r
4784     public void setMaximumSignificantDigits(int max) {\r
4785         if (max < 1) {\r
4786             max = 1;\r
4787         }\r
4788         // pin min sig dig to 1..max\r
4789         int min = Math.min(minSignificantDigits, max);\r
4790         minSignificantDigits = min;\r
4791         maxSignificantDigits = max;\r
4792     }\r
4793 \r
4794     /**\r
4795      * {@icu} Returns true if significant digits are in use or false if integer and\r
4796      * fraction digit counts are in use.\r
4797      *\r
4798      * @return true if significant digits are in use\r
4799      * @stable ICU 3.0\r
4800      */\r
4801     public boolean areSignificantDigitsUsed() {\r
4802         return useSignificantDigits;\r
4803     }\r
4804 \r
4805     /**\r
4806      * {@icu} Sets whether significant digits are in use, or integer and fraction digit\r
4807      * counts are in use.\r
4808      *\r
4809      * @param useSignificantDigits true to use significant digits, or false to use integer\r
4810      * and fraction digit counts\r
4811      * @stable ICU 3.0\r
4812      */\r
4813     public void setSignificantDigitsUsed(boolean useSignificantDigits) {\r
4814         this.useSignificantDigits = useSignificantDigits;\r
4815     }\r
4816 \r
4817     /**\r
4818      * Sets the <tt>Currency</tt> object used to display currency amounts. This takes\r
4819      * effect immediately, if this format is a currency format. If this format is not a\r
4820      * currency format, then the currency object is used if and when this object becomes a\r
4821      * currency format through the application of a new pattern.\r
4822      *\r
4823      * @param theCurrency new currency object to use. Must not be null.\r
4824      * @stable ICU 2.2\r
4825      */\r
4826     public void setCurrency(Currency theCurrency) {\r
4827         // If we are a currency format, then modify our affixes to\r
4828         // encode the currency symbol for the given currency in our\r
4829         // locale, and adjust the decimal digits and rounding for the\r
4830         // given currency.\r
4831 \r
4832         super.setCurrency(theCurrency);\r
4833         if (theCurrency != null) {\r
4834             boolean[] isChoiceFormat = new boolean[1];\r
4835             String s = theCurrency.getName(symbols.getULocale(),\r
4836                                            Currency.SYMBOL_NAME, isChoiceFormat);\r
4837             symbols.setCurrencySymbol(s);\r
4838             symbols.setInternationalCurrencySymbol(theCurrency.getCurrencyCode());\r
4839         }\r
4840 \r
4841         if (currencySignCount > 0) {\r
4842             if (theCurrency != null) {\r
4843                 setRoundingIncrement(theCurrency.getRoundingIncrement());\r
4844                 int d = theCurrency.getDefaultFractionDigits();\r
4845                 setMinimumFractionDigits(d);\r
4846                 setMaximumFractionDigits(d);\r
4847             }\r
4848             expandAffixes(null);\r
4849         }\r
4850     }\r
4851 \r
4852     /**\r
4853      * Returns the currency in effect for this formatter. Subclasses should override this\r
4854      * method as needed. Unlike getCurrency(), this method should never return null.\r
4855      *\r
4856      * @internal\r
4857      * @deprecated This API is ICU internal only.\r
4858      */\r
4859     protected Currency getEffectiveCurrency() {\r
4860         Currency c = getCurrency();\r
4861         if (c == null) {\r
4862             c = Currency.getInstance(symbols.getInternationalCurrencySymbol());\r
4863         }\r
4864         return c;\r
4865     }\r
4866 \r
4867     /**\r
4868      * Sets the maximum number of digits allowed in the fraction portion of a number. This\r
4869      * override limits the fraction digit count to 340.\r
4870      *\r
4871      * @see NumberFormat#setMaximumFractionDigits\r
4872      * @stable ICU 2.0\r
4873      */\r
4874     public void setMaximumFractionDigits(int newValue) {\r
4875         super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));\r
4876     }\r
4877 \r
4878     /**\r
4879      * Sets the minimum number of digits allowed in the fraction portion of a number. This\r
4880      * override limits the fraction digit count to 340.\r
4881      *\r
4882      * @see NumberFormat#setMinimumFractionDigits\r
4883      * @stable ICU 2.0\r
4884      */\r
4885     public void setMinimumFractionDigits(int newValue) {\r
4886         super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));\r
4887     }\r
4888 \r
4889     /**\r
4890      * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The\r
4891      * default value is false.\r
4892      *\r
4893      * @param value true if {@link #parse(String, ParsePosition)}\r
4894      * returns BigDecimal.\r
4895      * @stable ICU 3.6\r
4896      */\r
4897     public void setParseBigDecimal(boolean value) {\r
4898         parseBigDecimal = value;\r
4899     }\r
4900 \r
4901     /**\r
4902      * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal.\r
4903      *\r
4904      * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal.\r
4905      * @stable ICU 3.6\r
4906      */\r
4907     public boolean isParseBigDecimal() {\r
4908         return parseBigDecimal;\r
4909     }\r
4910 \r
4911     private void writeObject(ObjectOutputStream stream) throws IOException {\r
4912         // Ticket#6449 Format.Field instances are not serializable. When\r
4913         // formatToCharacterIterator is called, attributes (ArrayList) stores\r
4914         // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is\r
4915         // not serializable, we need to clear the contents of the list when writeObject is\r
4916         // called. We could remove the field or make it transient, but it will break\r
4917         // serialization compatibility.\r
4918         attributes.clear();\r
4919 \r
4920         stream.defaultWriteObject();\r
4921     }\r
4922 \r
4923     /**\r
4924      * First, read the default serializable fields from the stream. Then if\r
4925      * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was\r
4926      * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since\r
4927      * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the\r
4928      * maximum allowed value so that default serialization will work properly if this\r
4929      * object is streamed out again.\r
4930      */\r
4931     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {\r
4932         stream.defaultReadObject();\r
4933 \r
4934         // Bug 4185761 validate fields [Richard/GCL]\r
4935 \r
4936         // We only need to check the maximum counts because NumberFormat .readObject has\r
4937         // already ensured that the maximum is greater than the minimum count.\r
4938 \r
4939         // Commented for compatibility with previous version, and reserved for further use\r
4940         // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||\r
4941         // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new\r
4942         // InvalidObjectException("Digit count out of range"); }\r
4943 \r
4944 \r
4945         // Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and\r
4946         // maximumFractionDigits to DOUBLE_FRACTION_DIGITS\r
4947 \r
4948         if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) {\r
4949             setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);\r
4950         }\r
4951         if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {\r
4952             setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);\r
4953         }\r
4954         if (serialVersionOnStream < 2) {\r
4955             exponentSignAlwaysShown = false;\r
4956             setInternalRoundingIncrement(null);\r
4957             setRoundingDouble();\r
4958             roundingMode = BigDecimal.ROUND_HALF_EVEN;\r
4959             formatWidth = 0;\r
4960             pad = ' ';\r
4961             padPosition = PAD_BEFORE_PREFIX;\r
4962             if (serialVersionOnStream < 1) {\r
4963                 // Didn't have exponential fields\r
4964                 useExponentialNotation = false;\r
4965             }\r
4966         }\r
4967         if (serialVersionOnStream < 3) {\r
4968             // Versions prior to 3 do not store a currency object.  Create one to match\r
4969             // the DecimalFormatSymbols object.\r
4970             setCurrencyForSymbols();\r
4971         }\r
4972         serialVersionOnStream = currentSerialVersion;\r
4973         digitList = new DigitList();\r
4974 \r
4975         if (roundingIncrement != null) {\r
4976             setInternalRoundingIncrement(new BigDecimal(roundingIncrement));\r
4977             setRoundingDouble();\r
4978         }\r
4979     }\r
4980 \r
4981     private void setInternalRoundingIncrement(BigDecimal value) {\r
4982         roundingIncrementICU = value;\r
4983         roundingIncrement = value == null ? null : value.toBigDecimal();\r
4984     }\r
4985 \r
4986     // ----------------------------------------------------------------------\r
4987     // INSTANCE VARIABLES\r
4988     // ----------------------------------------------------------------------\r
4989 \r
4990     private transient DigitList digitList = new DigitList();\r
4991 \r
4992     /**\r
4993      * The symbol used as a prefix when formatting positive numbers, e.g. "+".\r
4994      *\r
4995      * @serial\r
4996      * @see #getPositivePrefix\r
4997      */\r
4998     private String positivePrefix = "";\r
4999 \r
5000     /**\r
5001      * The symbol used as a suffix when formatting positive numbers. This is often an\r
5002      * empty string.\r
5003      *\r
5004      * @serial\r
5005      * @see #getPositiveSuffix\r
5006      */\r
5007     private String positiveSuffix = "";\r
5008 \r
5009     /**\r
5010      * The symbol used as a prefix when formatting negative numbers, e.g. "-".\r
5011      *\r
5012      * @serial\r
5013      * @see #getNegativePrefix\r
5014      */\r
5015     private String negativePrefix = "-";\r
5016 \r
5017     /**\r
5018      * The symbol used as a suffix when formatting negative numbers. This is often an\r
5019      * empty string.\r
5020      *\r
5021      * @serial\r
5022      * @see #getNegativeSuffix\r
5023      */\r
5024     private String negativeSuffix = "";\r
5025 \r
5026     /**\r
5027      * The prefix pattern for non-negative numbers. This variable corresponds to\r
5028      * <code>positivePrefix</code>.\r
5029      *\r
5030      * <p>This pattern is expanded by the method <code>expandAffix()</code> to\r
5031      * <code>positivePrefix</code> to update the latter to reflect changes in\r
5032      * <code>symbols</code>. If this variable is <code>null</code> then\r
5033      * <code>positivePrefix</code> is taken as a literal value that does not change when\r
5034      * <code>symbols</code> changes.  This variable is always <code>null</code> for\r
5035      * <code>DecimalFormat</code> objects older than stream version 2 restored from\r
5036      * stream.\r
5037      *\r
5038      * @serial\r
5039      */\r
5040     // [Richard/GCL]\r
5041     private String posPrefixPattern;\r
5042 \r
5043     /**\r
5044      * The suffix pattern for non-negative numbers. This variable corresponds to\r
5045      * <code>positiveSuffix</code>. This variable is analogous to\r
5046      * <code>posPrefixPattern</code>; see that variable for further documentation.\r
5047      *\r
5048      * @serial\r
5049      */\r
5050     // [Richard/GCL]\r
5051     private String posSuffixPattern;\r
5052 \r
5053     /**\r
5054      * The prefix pattern for negative numbers. This variable corresponds to\r
5055      * <code>negativePrefix</code>. This variable is analogous to\r
5056      * <code>posPrefixPattern</code>; see that variable for further documentation.\r
5057      *\r
5058      * @serial\r
5059      */\r
5060     // [Richard/GCL]\r
5061     private String negPrefixPattern;\r
5062 \r
5063     /**\r
5064      * The suffix pattern for negative numbers. This variable corresponds to\r
5065      * <code>negativeSuffix</code>. This variable is analogous to\r
5066      * <code>posPrefixPattern</code>; see that variable for further documentation.\r
5067      *\r
5068      * @serial\r
5069      */\r
5070     // [Richard/GCL]\r
5071     private String negSuffixPattern;\r
5072 \r
5073     /**\r
5074      * Formatter for ChoiceFormat-based currency names. If this field is not null, then\r
5075      * delegate to it to format currency symbols.\r
5076      *\r
5077      * @since ICU 2.6\r
5078      */\r
5079     private ChoiceFormat currencyChoice;\r
5080 \r
5081     /**\r
5082      * The multiplier for use in percent, permill, etc.\r
5083      *\r
5084      * @serial\r
5085      * @see #getMultiplier\r
5086      */\r
5087     private int multiplier = 1;\r
5088 \r
5089     /**\r
5090      * The number of digits between grouping separators in the integer portion of a\r
5091      * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true.\r
5092      *\r
5093      * @serial\r
5094      * @see #getGroupingSize\r
5095      * @see NumberFormat#isGroupingUsed\r
5096      */\r
5097     private byte groupingSize = 3; // invariant, > 0 if useThousands\r
5098 \r
5099     /**\r
5100      * The secondary grouping size. This is only used for Hindi numerals, which use a\r
5101      * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this\r
5102      * value is less than 1, then secondary grouping is equal to the primary grouping.\r
5103      *\r
5104      */\r
5105     private byte groupingSize2 = 0;\r
5106 \r
5107     /**\r
5108      * If true, forces the decimal separator to always appear in a formatted number, even\r
5109      * if the fractional part of the number is zero.\r
5110      *\r
5111      * @serial\r
5112      * @see #isDecimalSeparatorAlwaysShown\r
5113      */\r
5114     private boolean decimalSeparatorAlwaysShown = false;\r
5115 \r
5116     /**\r
5117      * The <code>DecimalFormatSymbols</code> object used by this format. It contains the\r
5118      * symbols used to format numbers, e.g. the grouping separator, decimal separator, and\r
5119      * so on.\r
5120      *\r
5121      * @serial\r
5122      * @see #setDecimalFormatSymbols\r
5123      * @see DecimalFormatSymbols\r
5124      */\r
5125     private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();\r
5126 \r
5127     /**\r
5128      * True to use significant digits rather than integer and fraction digit counts.\r
5129      *\r
5130      * @serial\r
5131      * @since ICU 3.0\r
5132      */\r
5133     private boolean useSignificantDigits = false;\r
5134 \r
5135     /**\r
5136      * The minimum number of significant digits to show. Must be >= 1 and <=\r
5137      * maxSignificantDigits. Ignored unless useSignificantDigits == true.\r
5138      *\r
5139      * @serial\r
5140      * @since ICU 3.0\r
5141      */\r
5142     private int minSignificantDigits = 1;\r
5143 \r
5144     /**\r
5145      * The maximum number of significant digits to show. Must be >=\r
5146      * minSignficantDigits. Ignored unless useSignificantDigits == true.\r
5147      *\r
5148      * @serial\r
5149      * @since ICU 3.0\r
5150      */\r
5151     private int maxSignificantDigits = 6;\r
5152 \r
5153     /**\r
5154      * True to force the use of exponential (i.e. scientific) notation\r
5155      * when formatting numbers.\r
5156      *\r
5157      *<p> Note that the JDK 1.2 public API provides no way to set this\r
5158      * field, even though it is supported by the implementation and\r
5159      * the stream format. The intent is that this will be added to the\r
5160      * API in the future.\r
5161      *\r
5162      * @serial\r
5163      */\r
5164     private boolean useExponentialNotation; // Newly persistent in JDK 1.2\r
5165 \r
5166     /**\r
5167      * The minimum number of digits used to display the exponent when a number is\r
5168      * formatted in exponential notation.  This field is ignored if\r
5169      * <code>useExponentialNotation</code> is not true.\r
5170      *\r
5171      * <p>Note that the JDK 1.2 public API provides no way to set this field, even though\r
5172      * it is supported by the implementation and the stream format. The intent is that\r
5173      * this will be added to the API in the future.\r
5174      *\r
5175      * @serial\r
5176      */\r
5177     private byte minExponentDigits; // Newly persistent in JDK 1.2\r
5178 \r
5179     /**\r
5180      * If true, the exponent is always prefixed with either the plus sign or the minus\r
5181      * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has\r
5182      * no effect unless <code>useExponentialNotation</code> is true.\r
5183      *\r
5184      * @serial\r
5185      * @since AlphaWorks NumberFormat\r
5186      */\r
5187     private boolean exponentSignAlwaysShown = false;\r
5188 \r
5189     /**\r
5190      * The value to which numbers are rounded during formatting. For example, if the\r
5191      * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3\r
5192      * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a\r
5193      * positive value if rounding is in effect. Default value <code>null</code>.\r
5194      *\r
5195      * @serial\r
5196      * @since AlphaWorks NumberFormat\r
5197      */\r
5198     // Note: this is kept in sync with roundingIncrementICU.\r
5199     // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal\r
5200     private java.math.BigDecimal roundingIncrement = null;\r
5201 \r
5202     /**\r
5203      * The value to which numbers are rounded during formatting. For example, if the\r
5204      * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3\r
5205      * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a\r
5206      * positive value if rounding is in effect. Default value <code>null</code>. WARNING:\r
5207      * the roundingIncrement value is the one serialized.\r
5208      *\r
5209      * @serial\r
5210      * @since AlphaWorks NumberFormat\r
5211      */\r
5212     private transient BigDecimal roundingIncrementICU = null;\r
5213 \r
5214     /**\r
5215      * The rounding increment as a double. If this value is <= 0, then no rounding is\r
5216      * done. This value is <code>roundingIncrementICU.doubleValue()</code>. Default value\r
5217      * 0.0.\r
5218      */\r
5219     private transient double roundingDouble = 0.0;\r
5220 \r
5221     /**\r
5222      * If the roundingDouble is the reciprocal of an integer (the most common case!), this\r
5223      * is set to be that integer.  Otherwise it is 0.0.\r
5224      */\r
5225     private transient double roundingDoubleReciprocal = 0.0;\r
5226 \r
5227     /**\r
5228      * The rounding mode. This value controls any rounding operations which occur when\r
5229      * applying a rounding increment or when reducing the number of fraction digits to\r
5230      * satisfy a maximum fraction digits limit. The value may assume any of the\r
5231      * <code>BigDecimal</code> rounding mode values. Default value\r
5232      * <code>BigDecimal.ROUND_HALF_EVEN</code>.\r
5233      *\r
5234      * @serial\r
5235      * @since AlphaWorks NumberFormat\r
5236      */\r
5237     private int roundingMode = BigDecimal.ROUND_HALF_EVEN;\r
5238 \r
5239     /**\r
5240      * Operations on <code>BigDecimal</code> numbers are controlled by a {@link\r
5241      * MathContext} object, which provides the context (precision and other information)\r
5242      * for the operation. The default <code>MathContext</code> settings are\r
5243      * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>;\r
5244      * these settings perform fixed point arithmetic with unlimited precision, as defined\r
5245      * for the original BigDecimal class in Java 1.1 and Java 1.2\r
5246      */\r
5247     // context for plain unlimited math\r
5248     private MathContext mathContext = new MathContext(0, MathContext.PLAIN);\r
5249 \r
5250     /**\r
5251      * The padded format width, or zero if there is no padding. Must be >= 0. Default\r
5252      * value zero.\r
5253      *\r
5254      * @serial\r
5255      * @since AlphaWorks NumberFormat\r
5256      */\r
5257     private int formatWidth = 0;\r
5258 \r
5259     /**\r
5260      * The character used to pad the result of format to <code>formatWidth</code>, if\r
5261      * padding is in effect. Default value ' '.\r
5262      *\r
5263      * @serial\r
5264      * @since AlphaWorks NumberFormat\r
5265      */\r
5266     private char pad = ' ';\r
5267 \r
5268     /**\r
5269      * The position in the string at which the <code>pad</code> character will be\r
5270      * inserted, if padding is in effect.  Must have a value from\r
5271      * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value\r
5272      * <code>PAD_BEFORE_PREFIX</code>.\r
5273      *\r
5274      * @serial\r
5275      * @since AlphaWorks NumberFormat\r
5276      */\r
5277     private int padPosition = PAD_BEFORE_PREFIX;\r
5278 \r
5279     /**\r
5280      * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than\r
5281      * Long, Double or BigDecimal except special values. This property is introduced for\r
5282      * J2SE 5 compatibility support.\r
5283      *\r
5284      * @serial\r
5285      * @since ICU 3.6\r
5286      * @see #setParseBigDecimal(boolean)\r
5287      * @see #isParseBigDecimal()\r
5288      */\r
5289     private boolean parseBigDecimal = false;\r
5290 \r
5291     // ----------------------------------------------------------------------\r
5292 \r
5293     static final int currentSerialVersion = 3;\r
5294 \r
5295     /**\r
5296      * The internal serial version which says which version was written Possible values\r
5297      * are:\r
5298      *\r
5299      * <ul>\r
5300      *\r
5301      * <li><b>0</b> (default): versions before JDK 1.2\r
5302      *\r
5303      * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields\r
5304      * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.\r
5305      *\r
5306      * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad,\r
5307      * padPosition, exponentSignAlwaysShown, roundingIncrement.\r
5308      *\r
5309      * <li><b>3</b>: ICU 2.2. Adds currency object.\r
5310      *\r
5311      * </ul>\r
5312      *\r
5313      * @serial\r
5314      */\r
5315     private int serialVersionOnStream = currentSerialVersion;\r
5316 \r
5317     // ----------------------------------------------------------------------\r
5318     // CONSTANTS\r
5319     // ----------------------------------------------------------------------\r
5320 \r
5321     /**\r
5322      * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to\r
5323      * specify pad characters inserted before the prefix.\r
5324      *\r
5325      * @see #setPadPosition\r
5326      * @see #getPadPosition\r
5327      * @see #PAD_AFTER_PREFIX\r
5328      * @see #PAD_BEFORE_SUFFIX\r
5329      * @see #PAD_AFTER_SUFFIX\r
5330      * @stable ICU 2.0\r
5331      */\r
5332     public static final int PAD_BEFORE_PREFIX = 0;\r
5333 \r
5334     /**\r
5335      * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to\r
5336      * specify pad characters inserted after the prefix.\r
5337      *\r
5338      * @see #setPadPosition\r
5339      * @see #getPadPosition\r
5340      * @see #PAD_BEFORE_PREFIX\r
5341      * @see #PAD_BEFORE_SUFFIX\r
5342      * @see #PAD_AFTER_SUFFIX\r
5343      * @stable ICU 2.0\r
5344      */\r
5345     public static final int PAD_AFTER_PREFIX = 1;\r
5346 \r
5347     /**\r
5348      * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to\r
5349      * specify pad characters inserted before the suffix.\r
5350      *\r
5351      * @see #setPadPosition\r
5352      * @see #getPadPosition\r
5353      * @see #PAD_BEFORE_PREFIX\r
5354      * @see #PAD_AFTER_PREFIX\r
5355      * @see #PAD_AFTER_SUFFIX\r
5356      * @stable ICU 2.0\r
5357      */\r
5358     public static final int PAD_BEFORE_SUFFIX = 2;\r
5359 \r
5360     /**\r
5361      * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to\r
5362      * specify pad characters inserted after the suffix.\r
5363      *\r
5364      * @see #setPadPosition\r
5365      * @see #getPadPosition\r
5366      * @see #PAD_BEFORE_PREFIX\r
5367      * @see #PAD_AFTER_PREFIX\r
5368      * @see #PAD_BEFORE_SUFFIX\r
5369      * @stable ICU 2.0\r
5370      */\r
5371     public static final int PAD_AFTER_SUFFIX = 3;\r
5372 \r
5373     // Constants for characters used in programmatic (unlocalized) patterns.\r
5374     private static final char PATTERN_ZERO_DIGIT = '0';\r
5375     private static final char PATTERN_GROUPING_SEPARATOR = ',';\r
5376     private static final char PATTERN_DECIMAL_SEPARATOR = '.';\r
5377     private static final char PATTERN_DIGIT = '#';\r
5378     static final char PATTERN_SIGNIFICANT_DIGIT = '@';\r
5379     static final char PATTERN_EXPONENT = 'E';\r
5380     static final char PATTERN_PLUS_SIGN = '+';\r
5381 \r
5382     // Affix\r
5383     private static final char PATTERN_PER_MILLE = '\u2030';\r
5384     private static final char PATTERN_PERCENT = '%';\r
5385     static final char PATTERN_PAD_ESCAPE = '*';\r
5386     /**\r
5387      * Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]\r
5388      */\r
5389     private static final char PATTERN_MINUS = '-';\r
5390 \r
5391     // Other\r
5392     private static final char PATTERN_SEPARATOR = ';';\r
5393 \r
5394     // Pad escape is package private to allow access by DecimalFormatSymbols.\r
5395     // Also plus sign. Also exponent.\r
5396 \r
5397     /**\r
5398      * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in\r
5399      * patterns and substitued with either the currency symbol, or if it is doubled, with\r
5400      * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then\r
5401      * the decimal separator is replaced with the monetary decimal separator.\r
5402      *\r
5403      * The CURRENCY_SIGN is not localized.\r
5404      */\r
5405     private static final char CURRENCY_SIGN = '\u00A4';\r
5406 \r
5407     private static final char QUOTE = '\'';\r
5408 \r
5409     /**\r
5410      * Upper limit on integer and fraction digits for a Java double [Richard/GCL]\r
5411      */\r
5412     static final int DOUBLE_INTEGER_DIGITS = 309;\r
5413     static final int DOUBLE_FRACTION_DIGITS = 340;\r
5414 \r
5415     /**\r
5416      * When someone turns on scientific mode, we assume that more than this number of\r
5417      * digits is due to flipping from some other mode that didn't restrict the maximum,\r
5418      * and so we force 1 integer digit. We don't bother to track and see if someone is\r
5419      * using exponential notation with more than this number, it wouldn't make sense\r
5420      * anyway, and this is just to make sure that someone turning on scientific mode with\r
5421      * default settings doesn't end up with lots of zeroes.\r
5422      */\r
5423     static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8;\r
5424 \r
5425     // Proclaim JDK 1.1 serial compatibility.\r
5426     private static final long serialVersionUID = 864413376551465018L;\r
5427 \r
5428     private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>();\r
5429 \r
5430     // The following are used in currency format\r
5431 \r
5432     // -- triple currency sign char array\r
5433     // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4};\r
5434     // -- triple currency sign string\r
5435     // private static final String tripleCurrencyStr = new String(tripleCurrencySign);\r
5436     //\r
5437     // -- default currency plural pattern char array\r
5438     // private static final char[] defaultCurrencyPluralPatternChar =\r
5439     //   {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4};\r
5440     // -- default currency plural pattern string\r
5441     // private static final String defaultCurrencyPluralPattern =\r
5442     //     new String(defaultCurrencyPluralPatternChar);\r
5443 \r
5444     // pattern used in this formatter\r
5445     private String formatPattern = "";\r
5446     // style is only valid when decimal formatter is constructed by\r
5447     // DecimalFormat(pattern, decimalFormatSymbol, style)\r
5448     private int style = NumberFormat.NUMBERSTYLE;\r
5449     /**\r
5450      * Represents whether this is a currency format, and which currency format style. 0:\r
5451      * not currency format type; 1: currency style -- symbol name, such as "$" for US\r
5452      * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style\r
5453      * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for\r
5454      * "3.00 US Dollars".\r
5455      */\r
5456     private int currencySignCount = 0;\r
5457 \r
5458     /**\r
5459      * For parsing purposes, we need to remember all prefix patterns and suffix patterns\r
5460      * of every currency format pattern, including the pattern of the default currency\r
5461      * style, ISO currency style, and plural currency style. The patterns are set through\r
5462      * applyPattern. The following are used to represent the affix patterns in currency\r
5463      * plural formats.\r
5464      */\r
5465     private static final class AffixForCurrency {\r
5466         // negative prefix pattern\r
5467         private String negPrefixPatternForCurrency = null;\r
5468         // negative suffix pattern\r
5469         private String negSuffixPatternForCurrency = null;\r
5470         // positive prefix pattern\r
5471         private String posPrefixPatternForCurrency = null;\r
5472         // positive suffix pattern\r
5473         private String posSuffixPatternForCurrency = null;\r
5474         private int patternType;\r
5475 \r
5476         public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix,\r
5477                                 String posSuffix, int type) {\r
5478             negPrefixPatternForCurrency = negPrefix;\r
5479             negSuffixPatternForCurrency = negSuffix;\r
5480             posPrefixPatternForCurrency = posPrefix;\r
5481             posSuffixPatternForCurrency = posSuffix;\r
5482             patternType = type;\r
5483         }\r
5484 \r
5485         public String getNegPrefix() {\r
5486             return negPrefixPatternForCurrency;\r
5487         }\r
5488 \r
5489         public String getNegSuffix() {\r
5490             return negSuffixPatternForCurrency;\r
5491         }\r
5492 \r
5493         public String getPosPrefix() {\r
5494             return posPrefixPatternForCurrency;\r
5495         }\r
5496 \r
5497         public String getPosSuffix() {\r
5498             return posSuffixPatternForCurrency;\r
5499         }\r
5500 \r
5501         public int getPatternType() {\r
5502             return patternType;\r
5503         }\r
5504     }\r
5505 \r
5506     // Affix pattern set for currency.  It is a set of AffixForCurrency, each element of\r
5507     // the set saves the negative prefix, negative suffix, positive prefix, and positive\r
5508     // suffix of a pattern.\r
5509     private transient Set<AffixForCurrency> affixPatternsForCurrency = null;\r
5510 \r
5511     // For currency parsing. Since currency parsing needs to parse against all currency\r
5512     // patterns, before the parsing, we need to set up the affix patterns for all currencies.\r
5513     private transient boolean isReadyForParsing = false;\r
5514 \r
5515     // Information needed for DecimalFormat to format/parse currency plural.\r
5516     private CurrencyPluralInfo currencyPluralInfo = null;\r
5517 }\r
5518 \r
5519 // eof\r