17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 1996-2014, International Business Machines Corporation and * 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. * 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException; 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectInputStream; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectOutputStream; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.math.BigInteger; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.AttributedCharacterIterator; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.AttributedString; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ChoiceFormat; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.Format; 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParsePosition; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.ArrayList; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.HashSet; 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Iterator; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUConfig; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.PatternProps; 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Utility; 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter; 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.math.BigDecimal; 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.math.MathContext; 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.FixedDecimal; 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Currency; 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Currency.CurrencyUsage; 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.CurrencyAmount; 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale.Category; 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_} 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> is a concrete subclass of {@link NumberFormat} that formats 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * decimal numbers. It has a variety of features designed to make it possible to parse and 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format numbers in any locale, including support for Western, Arabic, or Indic digits. 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It also supports different flavors of numbers, including integers ("123"), fixed-point 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * amounts ("$123.00", "USD123.00", "123.00 US dollars"). All of these flavors can be 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * easily localized. 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To obtain a {@link NumberFormat} for a specific locale (including the default 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale) call one of <code>NumberFormat</code>'s factory methods such as {@link 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat#getInstance}. Do not call the <code>DecimalFormat</code> constructors 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * directly, unless you know what you are doing, since the {@link NumberFormat} factory 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * methods may return subclasses other than <code>DecimalFormat</code>. If you need to 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * customize the format object, do something like this: 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre> 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat f = NumberFormat.getInstance(loc); 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if (f instanceof DecimalFormat) { 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true); 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * }</pre></blockquote> 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><strong>Example Usage</strong> 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Print out a number using the localized number, currency, and percent 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format for each locale. 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre> 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Locale[] locales = NumberFormat.getAvailableLocales(); 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * double myNumber = -1234.56; 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat format; 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for (int j=0; j<3; ++j) { 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * System.out.println("FORMAT"); 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for (int i = 0; i < locales.length; ++i) { 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if (locales[i].getCountry().length() == 0) { 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Skip language-only locales 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * continue; 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * System.out.print(locales[i].getDisplayName()); 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * switch (j) { 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * case 0: 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format = NumberFormat.getInstance(locales[i]); break; 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * case 1: 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format = NumberFormat.getCurrencyInstance(locales[i]); break; 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * default: 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format = NumberFormat.getPercentInstance(locales[i]); break; 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * try { 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Assume format is a DecimalFormat 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * System.out.print(": " + ((DecimalFormat) format).toPattern() 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * + " -> " + form.format(myNumber)); 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } catch (Exception e) {} 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * try { 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * System.out.println(" -> " + format.parse(form.format(myNumber))); 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } catch (ParseException e) {} 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * }</pre></blockquote> 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Another example use getInstance(style).<br/> 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Print out a number using the localized number, currency, percent, 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * scientific, integer, iso currency, and plural currency format for each locale. 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre> 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ULocale locale = new ULocale("en_US"); 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * double myNumber = 1234.56; 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for (int j=NumberFormat.NUMBERSTYLE; j<=NumberFormat.PLURALCURRENCYSTYLE; ++j) { 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat format = NumberFormat.getInstance(locale, j); 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * try { 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * // Assume format is a DecimalFormat 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * System.out.print(": " + ((DecimalFormat) format).toPattern() 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * + " -> " + form.format(myNumber)); 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } catch (Exception e) {} 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * try { 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * System.out.println(" -> " + format.parse(form.format(myNumber))); 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * } catch (ParseException e) {} 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * }</pre></blockquote> 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Patterns</h4> 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>A <code>DecimalFormat</code> consists of a <em>pattern</em> and a set of 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>symbols</em>. The pattern may be set directly using {@link #applyPattern}, or 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * indirectly using other API methods which manipulate aspects of the pattern, such as the 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * minimum number of integer digits. The symbols are stored in a {@link 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols} object. When using the {@link NumberFormat} factory methods, the 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern and symbols are read from ICU's locale data. 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Special Pattern Characters</h4> 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Many characters in a pattern are taken literally; they are matched during parsing 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and output unchanged during formatting. Special characters, on the other hand, stand 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for other characters, strings, or classes of characters. For example, the '#' 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * character is replaced by a localized digit. Often the replacement character is the 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * same as the pattern character; in the U.S. locale, the ',' grouping character is 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * replaced by ','. However, the replacement is still happening, and if the symbols are 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * modified, the grouping character changes. Some special characters affect the behavior 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of the formatter by their presence; for example, if the percent character is seen, then 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the value is multiplied by 100 before being displayed. 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To insert a special character in a pattern as a literal, that is, without any 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * special meaning, the character must be quoted. There are some exceptions to this which 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are noted below. 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The characters listed here are used in non-localized patterns. Localized patterns 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use the corresponding characters taken from this formatter's {@link 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols} object instead, and these characters lose their special status. 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Two exceptions are the currency sign and quote, which are not localized. 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote> 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol, 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * location, localized, and meaning."> 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr bgcolor="#ccccff"> 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Symbol 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Location 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Localized? 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Meaning 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>0</code> 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Digit 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>1-9</code> 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>'1' through '9' indicate rounding. 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>@</code> 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>No 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Significant digit 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>#</code> 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Digit, zero shows as absent 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>.</code> 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Decimal separator or monetary decimal separator 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>-</code> 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Minus sign 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>,</code> 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Grouping separator 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>E</code> 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Number 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Separates mantissa and exponent in scientific notation. 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>Need not be quoted in prefix or suffix.</em> 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>+</code> 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Exponent 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Prefix positive exponents with localized plus sign. 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>Need not be quoted in prefix or suffix.</em> 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>;</code> 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Subpattern boundary 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Separates positive and negative subpatterns 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>%</code> 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Prefix or suffix 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Multiply by 100 and show as percentage 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>\u2030</code> 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Prefix or suffix 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Multiply by 1000 and show as per mille 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>¤</code> (<code>\u00A4</code>) 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Prefix or suffix 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>No 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Currency sign, replaced by currency symbol. If 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * doubled, replaced by international currency symbol. 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If tripled, replaced by currency plural names, for example, 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "US dollar" or "US dollars" for America. 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If present in a pattern, the monetary decimal separator 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is used instead of the decimal separator. 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>'</code> 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Prefix or suffix 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>No 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Used to quote special characters in a prefix or suffix, 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for example, <code>"'#'#"</code> formats 123 to 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"#123"</code>. To create a single quote 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * itself, use two in a row: <code>"# o''clock"</code>. 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>*</code> 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Prefix or suffix boundary 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Yes 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>Pad escape, precedes pad character 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </table> 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote> 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>A <code>DecimalFormat</code> pattern contains a postive and negative subpattern, for 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, "#,##0.00;(#,##0.00)". Each subpattern has a prefix, a numeric part, and a 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix. If there is no explicit negative subpattern, the negative subpattern is the 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * equivalent to "0.00;-0.00". If there is an explicit negative subpattern, it serves 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * only to specify the negative prefix and suffix; the number of digits, minimal digits, 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and other characteristics are ignored in the negative subpattern. That means that 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)". 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The prefixes, suffixes, and various symbols used for infinity, digits, thousands 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separators, decimal separators, etc. may be set to arbitrary values, and they will 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * appear properly during formatting. However, care must be taken that the symbols and 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * strings do not conflict, or parsing will be unreliable. For example, either the 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * positive and negative prefixes or the suffixes must be distinct for {@link #parse} to 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be able to distinguish positive from negative values. Another example is that the 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * decimal separator and thousands separator should be distinct characters, or parsing 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be impossible. 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>The <em>grouping separator</em> is a character that separates clusters of integer 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits to make large numbers more legible. It commonly used for thousands, but in some 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locales it separates ten-thousands. The <em>grouping size</em> is the number of digits 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0000". There are actually two different grouping sizes: One used for the least 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant integer digits, the <em>primary grouping size</em>, and one used for all 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others, the <em>secondary grouping size</em>. In most locales these are the same, but 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sometimes they are different. For example, if the primary grouping interval is 3, and 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 123456789 is formatted as "12,34,56,789". If a pattern contains multiple grouping 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separators, the interval between the last one and the end of the integer defines the 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * primary grouping size, and the interval between the last two defines the secondary 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" == 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "##,#,###,####". 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> to throw an {@link IllegalArgumentException} with a message 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that describes the problem. 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Pattern BNF</h4> 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <pre> 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern := subpattern (';' subpattern)? 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * subpattern := prefix? number exponent? suffix? 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number := (integer ('.' fraction)?) | sigDigits 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * prefix := '\u0000'..'\uFFFD' - specialCharacters 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix := '\u0000'..'\uFFFD' - specialCharacters 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * integer := '#'* '0'* '0' 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction := '0'* '#'* 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sigDigits := '#'* '@' '@'* '#'* 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exponent := 'E' '+'? '0'* '0' 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padSpec := '*' padChar 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padChar := '\u0000'..'\uFFFD' - quote 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *   2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Notation: 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * X* 0 or more instances of X 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * X? 0 or 1 instances of X 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * X|Y either X or Y 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * C..D any character from C up to D, inclusive 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * S-T characters in S, except those in T 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre> 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The first subpattern is for positive numbers. The second (optional) 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * subpattern is for negative numbers. 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Not indicated in the BNF syntax above: 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The grouping separator ',' can occur inside the integer and sigDigits 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * elements, between any two pattern characters of that element, as long as the integer or 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sigDigits element is not followed by the exponent element. 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Two grouping intervals are recognized: That between the decimal point and the first 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * grouping symbol, and that between the first and second grouping symbols. These 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * intervals are identical in most locales, but in some locales they differ. For example, 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the pattern "#,##,###" formats the number 123456789 as 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "12,34,56,789". 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * prefix, before the suffix, after the suffix, or not at all. 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * increment. 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Parsing</h4> 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits, as defined by {@link UCharacter#digit}. In addition, 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> also recognizes as digits the ten consecutive characters 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * starting with the localized zero digit defined in the {@link DecimalFormatSymbols} 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. During formatting, the {@link DecimalFormatSymbols}-based digits are output. 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>During parsing, grouping separators are ignored. 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>For currency parsing, the formatter is able to parse every currency style formats no 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * matter which style the formatter is constructed with. For example, a formatter 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * instance gotten from NumberFormat.getInstance(ULocale, NumberFormat.CURRENCYSTYLE) can 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parse formats such as "USD1.00" and "3.00 US dollars". 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>null</code> and leaves the parse position unchanged. The convenience method 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link #parse(String)} indicates parse failure by throwing a {@link 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * java.text.ParseException}. 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Parsing an extremely large or small absolute value (such as 1.0E10000 or 1.0E-10000) 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * requires huge memory allocation for representing the parsed number. Such input may expose 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a risk of DoS attacks. To prevent huge memory allocation triggered by such inputs, 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> internally limits of maximum decimal digits to be 1000. Thus, 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * an input string resulting more than 1000 digits in plain decimal representation (non-exponent) 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be treated as either overflow (positive/negative infinite) or underflow (+0.0/-0.0). 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Formatting</h4> 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Formatting is guided by several parameters, all of which can be specified either 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * using a pattern or using the API. The following description applies to formats that do 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not use <a href="#sci">scientific notation</a> or <a href="#sigdig">significant 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</a>. 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul><li>If the number of actual integer digits exceeds the <em>maximum integer 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then only the least significant digits are shown. For example, 1997 is 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatted as "97" if the maximum integer digits is set to 2. 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If the number of actual integer digits is less than the <em>minimum integer 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then leading zeros are added. For example, 1997 is formatted as "01997" 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if the minimum integer digits is set to 5. 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If the number of actual fraction digits exceeds the <em>maximum fraction 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then half-even rounding it performed to the maximum fraction digits. For 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, 0.125 is formatted as "0.12" if the maximum fraction digits is 2. This 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * behavior can be changed by specifying a rounding increment and a rounding mode. 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If the number of actual fraction digits is less than the <em>minimum fraction 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits</em>, then trailing zeros are added. For example, 0.125 is formatted as 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "0.1250" if the mimimum fraction digits is set to 4. 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Trailing fractional zeros are not displayed if they occur <em>j</em> positions 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * after the decimal, where <em>j</em> is less than the maximum fraction digits. For 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, 0.10004 is formatted as "0.1" if the maximum fraction digits is four or less. 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><strong>Special Values</strong> 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>NaN</code> is represented as a single character, typically 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>\uFFFD</code>. This character is determined by the {@link 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols} object. This is the only value for which the prefixes and 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffixes are not used. 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Infinity is represented as a single character, typically <code>\u221E</code>, 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with the positive or negative prefixes and suffixes applied. The infinity character is 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * determined by the {@link DecimalFormatSymbols} object. 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <a name="sci"><h4>Scientific Notation</h4></a> 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Numbers in scientific notation are expressed as the product of a mantissa and a 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * power of ten, for example, 1234 can be expressed as 1.234 x 10<sup>3</sup>. The 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0), 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but it need not be. <code>DecimalFormat</code> supports arbitrary mantissas. 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> can be instructed to use scientific notation through the API 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or through the pattern. In a pattern, the exponent character immediately followed by 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * one or more digit characters indicates scientific notation. Example: "0.###E0" formats 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the number 1234 as "1.234E3". 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The number of digit characters after the exponent character gives the minimum 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exponent digit count. There is no maximum. Negative exponents are formatted using the 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * localized minus sign, <em>not</em> the prefix and suffix from the pattern. This allows 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns such as "0.###E0 m/s". To prefix positive exponents with a localized plus 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sign, specify '+' between the exponent and the digits: "0.###E+0" will produce formats 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "1E+1", "1E+0", "1E-1", etc. (In localized patterns, use the localized plus sign 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rather than '+'.) 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The minimum number of integer digits is achieved by adjusting the exponent. 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Example: 0.00123 formatted with "00.###E0" yields "12.3E-4". This only happens if 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * there is no maximum number of integer digits. If there is a maximum, then the minimum 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number of integer digits is fixed at one. 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The maximum number of integer digits, if present, specifies the exponent grouping. 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The most common use of this is to generate <em>engineering notation</em>, in which the 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * exponent is a multiple of three, e.g., "##0.###E0". The number 12345 is formatted 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * using "##0.####E0" as "12.345E3". 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>When using scientific notation, the formatter controls the digit counts using 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant digits logic. The maximum number of significant digits limits the total 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number of integer and fraction digits that will be shown in the mantissa; it does not 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * affect parsing. For example, 12345 formatted with "##0.##E0" is "12.3E3". See the 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * section on significant digits for more details. 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The number of significant digits shown is determined as follows: If 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * areSignificantDigitsUsed() returns false, then the minimum number of significant digits 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * shown is one, and the maximum number of significant digits shown is the sum of the 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is unaffected by the 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maximum integer digits. If this sum is zero, then all significant digits are shown. 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If areSignificantDigitsUsed() returns true, then the significant digit counts are 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specified by getMinimumSignificantDigits() and getMaximumSignificantDigits(). In this 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * case, the number of integer digits is fixed at one, and there is no exponent grouping. 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Exponential patterns may not contain grouping separators. 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <a name="sigdig"><h4>Significant Digits</h4></a> 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> has two ways of controlling how many digits are shows: (a) 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant digits counts, or (b) integer and fraction digit counts. Integer and 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digit counts are described above. When a formatter is using significant 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits counts, the number of integer and fraction digits is not specified directly, and 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the formatter settings for these counts are ignored. Instead, the formatter uses 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * however many integer and fraction digits are required to display the specified number 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of significant digits. Examples: 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote> 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <table border=0 cellspacing=3 cellpadding=0> 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr bgcolor="#ccccff"> 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Pattern 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Minimum significant digits 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Maximum significant digits 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Number 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <th align=left>Output of format() 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>@@@</code> 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>12345 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>12300</code> 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>@@@</code> 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>0.12345 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>0.123</code> 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top> 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>@@##</code> 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>4 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>3.14159 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>3.142</code> 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <tr valign=top bgcolor="#eeeeff"> 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>@@##</code> 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>2 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>4 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td>1.23004 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <td><code>1.23</code> 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </table> 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </blockquote> 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Significant digit counts may be expressed using patterns that specify a minimum and 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maximum number of significant digits. These are indicated by the <code>'@'</code> and 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'#'</code> characters. The minimum number of significant digits is the number of 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'@'</code> characters. The maximum number of significant digits is the number of 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'@'</code> characters plus the number of <code>'#'</code> characters following on 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the right. For example, the pattern <code>"@@@"</code> indicates exactly 3 significant 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits. The pattern <code>"@##"</code> indicates from 1 to 3 significant digits. 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Trailing zero digits to the right of the decimal separator are suppressed after the 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * minimum number of significant digits have been shown. For example, the pattern 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"@##"</code> formats the number 0.1203 as <code>"0.12"</code>. 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If a pattern uses significant digits, it may not contain a decimal separator, nor 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the <code>'0'</code> pattern character. Patterns such as <code>"@00"</code> or 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"@.###"</code> are disallowed. 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Any number of <code>'#'</code> characters may be prepended to the left of the 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * leftmost <code>'@'</code> character. These have no effect on the minimum and maximum 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * significant digits counts, but may be used to position grouping separators. For 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * example, <code>"#,#@#"</code> indicates a minimum of one significant digits, a maximum 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of two significant digits, and a grouping size of three. 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In order to enable significant digits formatting, use a pattern containing the 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>'@'</code> pattern character. Alternatively, call {@link 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * #setSignificantDigitsUsed setSignificantDigitsUsed(true)}. 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In order to disable significant digits formatting, use a pattern that does not 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * contain the <code>'@'</code> pattern character. Alternatively, call {@link 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * #setSignificantDigitsUsed setSignificantDigitsUsed(false)}. 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The number of significant digits has no effect on parsing. 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Significant digits may be used together with exponential notation. Such patterns 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are equivalent to a normal exponential pattern with a minimum and maximum integer digit 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * count of one, a minimum fraction digit count of <code>getMinimumSignificantDigits() - 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1</code>, and a maximum fraction digit count of <code>getMaximumSignificantDigits() - 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1</code>. For example, the pattern <code>"@@###E0"</code> is equivalent to 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>"0.0###E0"</code>. 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>If signficant digits are in use, then the integer and fraction digit counts, as set 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * via the API, are ignored. If significant digits are not in use, then the signficant 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digit counts, as set via the API, are ignored. 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Padding</h4> 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> supports padding the result of {@link #format} to a 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specific width. Padding may be specified either through the API or through the pattern 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * syntax. In a pattern the pad escape character, followed by a single pad character, 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * causes padding to be parsed and formatted. The pad escape character is '*' in 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * unlocalized patterns, and can be localized using {@link 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols#setPadEscape}. For example, <code>"$*x#,##0.00"</code> formats 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 123 to <code>"$xx123.00"</code>, and 1234 to <code>"$1,234.00"</code>. 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>When padding is in effect, the width of the positive subpattern, including prefix 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and suffix, determines the format width. For example, in the pattern <code>"* #0 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * o''clock"</code>, the format width is 10. 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>The width is counted in 16-bit code units (Java <code>char</code>s). 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Some parameters which usually do not matter have meaning when padding is used, 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * because the pattern width is significant with padding. In the pattern "* 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ##,##,#,##0.##", the format width is 14. The initial characters "##,##," do not affect 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the grouping size or maximum integer digits, but they do affect the format width. 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Padding may be inserted at one of four locations: before the prefix, after the 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * prefix, before the suffix, or after the suffix. If padding is specified in any other 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * location, {@link #applyPattern} throws an {@link IllegalArgumentException}. If there 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is no prefix, before the prefix and after the prefix are equivalent, likewise for the 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix. 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>When specified in a pattern, the 16-bit <code>char</code> immediately following the 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pad escape is the pad character. This may be any character, including a special pattern 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * character. That is, the pad escape <em>escapes</em> the following character. If there 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is no character after the pad escape, then the pattern is illegal. 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <strong>Rounding</strong> 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> supports rounding to a specific increment. For example, 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1230 rounded to the nearest 50 is 1250. 1.234 rounded to the nearest 0.65 is 1.3. The 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment may be specified through the API or in a pattern. To specify a 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment in a pattern, include the increment in the pattern itself. "#,#50" 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specifies a rounding increment of 50. "#,##0.05" specifies a rounding increment of 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 0.05. 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Rounding only affects the string produced by formatting. It does not affect 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsing or change any numerical values. 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>A <em>rounding mode</em> determines how values are rounded; see the {@link 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * com.ibm.icu.math.BigDecimal} documentation for a description of the modes. Rounding 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * increments specified in patterns use the default mode, {@link 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN}. 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>Some locales use rounding in their currency formats to reflect the smallest 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency denomination. 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>In a pattern, digits '1' through '9' specify rounding, but otherwise behave 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * identically to digit '0'. 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Synchronization</h4> 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p><code>DecimalFormat</code> objects are not synchronized. Multiple threads should 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not access one formatter concurrently. 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.text.Format 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Mark Davis 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Alan Liu 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class DecimalFormat extends NumberFormat { 6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a DecimalFormat using the default pattern and symbols for the default 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * internationalization is not the main concern. 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To obtain standard formats for a given locale, use the factory methods on 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat such as getNumberInstance. These factories will return the most 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * appropriate sub-class of NumberFormat for a given locale. 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getInstance 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getNumberInstance 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getCurrencyInstance 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getPercentInstance 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DecimalFormat() { 6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale def = ULocale.getDefault(Category.FORMAT); 6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pattern = getPattern(def, 0); 6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Always applyPattern after the symbols are set 6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.symbols = new DecimalFormatSymbols(def); 6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrency(Currency.getInstance(def)); 6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(pattern, false); 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = new CurrencyPluralInfo(def); 6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the exact pattern is not known until the plural count is known. 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // so, no need to expand affix now. 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixAdjustWidth(null); 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a DecimalFormat from the given pattern and the symbols for the default 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>FORMAT</code> locale. This is a convenient way to obtain a DecimalFormat when 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * internationalization is not the main concern. 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To obtain standard formats for a given locale, use the factory methods on 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat such as getNumberInstance. These factories will return the most 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * appropriate sub-class of NumberFormat for a given locale. 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern A non-localized pattern string. 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the given pattern is invalid. 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getInstance 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getNumberInstance 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getCurrencyInstance 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getPercentInstance 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DecimalFormat(String pattern) { 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Always applyPattern after the symbols are set 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale def = ULocale.getDefault(Category.FORMAT); 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.symbols = new DecimalFormatSymbols(def); 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrency(Currency.getInstance(def)); 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(pattern, false); 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = new CurrencyPluralInfo(def); 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixAdjustWidth(null); 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a DecimalFormat from the given pattern and symbols. Use this constructor 6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when you need to completely customize the behavior of the format. 6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To obtain standard formats for a given locale, use the factory methods on 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat such as getInstance or getCurrencyInstance. If you need only minor 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * adjustments to a standard format, you can modify the format returned by a 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat factory method. 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern a non-localized pattern string 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param symbols the set of symbols to be used 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException if the given pattern is invalid 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getInstance 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getNumberInstance 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getCurrencyInstance 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#getPercentInstance 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols 6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DecimalFormat(String pattern, DecimalFormatSymbols symbols) { 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert createFromPatternAndSymbols(pattern, symbols); 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void createFromPatternAndSymbols(String pattern, DecimalFormatSymbols inputSymbols) { 6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Always applyPattern after the symbols are set 6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols = (DecimalFormatSymbols) inputSymbols.clone(); 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrencyForSymbols(); 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(pattern, false); 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale()); 7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixAdjustWidth(null); 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a DecimalFormat from the given pattern, symbols, information used for 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency plural format, and format style. Use this constructor when you need to 7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * completely customize the behavior of the format. 7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>To obtain standard formats for a given locale, use the factory methods on 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat such as getInstance or getCurrencyInstance. 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If you need only minor adjustments to a standard format, you can modify the 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format returned by a NumberFormat factory method using the setters. 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If you want to completely customize a decimal format, using your own 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * DecimalFormatSymbols (such as group separators) and your own information for 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency plural formatting (such as plural rule and currency plural patterns), you 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * can use this constructor. 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern a non-localized pattern string 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param symbols the set of symbols to be used 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param infoInput the information used for currency plural format, including 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency plural patterns and plural rules. 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param style the decimal formatting style, it is one of the following values: 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE; 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE; 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * NumberFormat.ISOCURRENCYSTYLE; NumberFormat.PLURALCURRENCYSTYLE; 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DecimalFormat(String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput, 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int style) { 7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CurrencyPluralInfo info = infoInput; 7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (style == NumberFormat.PLURALCURRENCYSTYLE) { 7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert info = (CurrencyPluralInfo) infoInput.clone(); 7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert create(pattern, symbols, info, style); 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void create(String pattern, DecimalFormatSymbols inputSymbols, CurrencyPluralInfo info, 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int inputStyle) { 7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (inputStyle != NumberFormat.PLURALCURRENCYSTYLE) { 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert createFromPatternAndSymbols(pattern, inputSymbols); 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Always applyPattern after the symbols are set 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols = (DecimalFormatSymbols) inputSymbols.clone(); 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = info; 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the pattern used in format is not fixed until formatting, in which, the 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // number is known and will be used to pick the right pattern based on plural 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count. Here, set the pattern as the pattern of plural count == "other". 7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For most locale, the patterns are probably the same for all plural 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count. If not, the right pattern need to be re-applied during format. 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String currencyPluralPatternForOther = 7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo.getCurrencyPluralPattern("other"); 7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(currencyPluralPatternForOther, false); 7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrencyForSymbols(); 7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert style = inputStyle; 7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a DecimalFormat for currency plural format from the given pattern, symbols, 7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and style. 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DecimalFormat(String pattern, DecimalFormatSymbols inputSymbols, int style) { 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CurrencyPluralInfo info = null; 7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (style == NumberFormat.PLURALCURRENCYSTYLE) { 7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert info = new CurrencyPluralInfo(inputSymbols.getULocale()); 7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert create(pattern, inputSymbols, info, style); 7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) { 7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(number, result, fieldPosition, false); 7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // See if number is negative. 7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // usage: isNegative(multiply(numberToBeFormatted)); 7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean isNegative(double number) { 7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Detecting whether a double is negative is easy with the exception of the value 7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -0.0. This is a double which has a zero mantissa (and exponent), but a negative 7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // sign bit. It is semantically distinct from a zero with a positive sign bit, and 7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // this distinction is important to certain kinds of computations. However, it's a 7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // little tricky to detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you 7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // may ask, does it behave distinctly from +0.0? Well, 1/(-0.0) == 7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -Infinity. Proper detection of -0.0 is needed to deal with the issues raised by 7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // bugs 4106658, 4106667, and 4147706. Liu 7/6/98. 7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (number < 0.0) || (number == 0.0 && 1 / number < 0.0); 7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Rounds the number and strips of the negative sign. 8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // usage: round(multiply(numberToBeFormatted)) 8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private double round(double number) { 8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative = isNegative(number); 8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isNegative) 8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = -number; 8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Apply rounding after multiplier 8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingDouble > 0.0) { 8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // number = roundingDouble 8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // * round(number / roundingDouble, roundingMode, isNegative); 8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return round( 8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number, roundingDouble, roundingDoubleReciprocal, roundingMode, 8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isNegative); 8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Multiplies given number by multipler (if there is one) returning the new 8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // number. If there is no multiplier, returns the number passed in unchanged. 8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private double multiply(double number) { 8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (multiplier != 1) { 8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number * multiplier; 8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] The actual method to format number. If boolean value 8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // parseAttr == true, then attribute information will be recorded. 8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition, 8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(0); 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(0); 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (Double.isNaN(number)) { 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(symbols.getNaN()); 8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for NaN here. 8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // result.append(symbols.getNaN()); 8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.INTEGER, result.length() - symbols.getNaN().length(), 8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.length()); 8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addPadding(result, fieldPosition, 0, 0); 8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do this BEFORE checking to see if value is negative or infinite and 8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // before rounding. 8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = multiply(number); 8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative = isNegative(number); 8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = round(number); 8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (Double.isInfinite(number)) { 8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int prefixLen = appendAffix(result, isNegative, true, parseAttr); 8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for infinity here. 8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(symbols.getInfinity()); 8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 8767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.INTEGER, result.length() - symbols.getInfinity().length(), 8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.length()); 8787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int suffixLen = appendAffix(result, isNegative, false, parseAttr); 8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addPadding(result, fieldPosition, prefixLen, suffixLen); 8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int precision = precision(false); 8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This is to fix rounding for scientific notation. See ticket:10542. 8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This code should go away when a permanent fix is done for ticket:9931. 8957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This block of code only executes for scientific notation so it will not interfere with the 8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // previous fix in {@link #resetActualRounding} for fixed decimal numbers. 8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Moreover this code only runs when there is rounding to be done (precision > 0) and when the 8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // rounding mode is something other than ROUND_HALF_EVEN. 9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This block of code does the correct rounding of number in advance so that it will fit into 9017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the number of digits indicated by precision. In this way, we avoid using the default 9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ROUND_HALF_EVEN behavior of DigitList. For example, if number = 0.003016 and roundingMode = 9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ROUND_DOWN and precision = 3 then after this code executes, number = 0.00301 (3 significant digits) 9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useExponentialNotation && precision > 0 && number != 0.0 && roundingMode != BigDecimal.ROUND_HALF_EVEN) { 9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int log10RoundingIncr = 1 - precision + (int) Math.floor(Math.log10(Math.abs(number))); 9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double roundingIncReciprocal = 0.0; 9077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double roundingInc = 0.0; 9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (log10RoundingIncr < 0) { 9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingIncReciprocal = 9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigDecimal.ONE.movePointRight(-log10RoundingIncr).doubleValue(); 9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingInc = 9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigDecimal.ONE.movePointRight(log10RoundingIncr).doubleValue(); 9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = DecimalFormat.round(number, roundingInc, roundingIncReciprocal, roundingMode, isNegative); 9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // End fix for ticket:10542 9187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // At this point we are guaranteed a nonnegative finite 9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // number. 9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (digitList) { 9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.set(number, precision, !useExponentialNotation && 9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert !areSignificantDigitsUsed()); 9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(number, result, fieldPosition, isNegative, false, parseAttr); 9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a special function used by the CompactDecimalFormat subclass. 9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It completes only the rounding portion of the formatting and returns 9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the resulting double. CompactDecimalFormat uses the result to compute 9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the plural form to use. 9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number The number to format. 9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The number rounded to the correct number of significant digits 9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with negative sign stripped off. 9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double adjustNumberAsInFormatting(double number) { 9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (Double.isNaN(number)) { 9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = round(multiply(number)); 9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (Double.isInfinite(number)) { 9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return toDigitList(number).getDouble(); 9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DigitList toDigitList(double number) { 9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DigitList result = new DigitList(); 9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.set(number, precision(false), false); 9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is a special function used by the CompactDecimalFormat subclass 9617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to determine if the number to be formatted is negative. 9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number The number to format. 9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return True if number is negative. 9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNumberNegative(double number) { 9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (Double.isNaN(number)) { 9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return isNegative(multiply(number)); 9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Round a double value to the nearest multiple of the given rounding increment, 9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * according to the given mode. This is equivalent to rounding value/roundingInc to 9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the nearest integer, according to the given mode, and returning that integer * 9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * roundingInc. Note this is changed from the version in 2.4, since division of 9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * doubles have inaccuracies. jitterbug 1871. 9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number 9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the absolute value of the number to be rounded 9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param roundingInc 9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the rounding increment 9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param roundingIncReciprocal 9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if non-zero, is the reciprocal of rounding inc. 9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param mode 9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a BigDecimal rounding mode 9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isNegative 9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * true if the number to be rounded is negative 9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the absolute value of the rounded result 9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static double round(double number, double roundingInc, double roundingIncReciprocal, 9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int mode, boolean isNegative) { 9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double div = roundingIncReciprocal == 0.0 ? number / roundingInc : number * 9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingIncReciprocal; 10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do the absolute cases first 10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (mode) { 10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_CEILING: 10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon)); 10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_FLOOR: 10087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon)); 10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_DOWN: 10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = (Math.floor(div + epsilon)); 10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_UP: 10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = (Math.ceil(div - epsilon)); 10157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_UNNECESSARY: 10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (div != Math.floor(div)) { 10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new ArithmeticException("Rounding necessary"); 10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: 10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle complex cases, where the choice depends on the closer value. 10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We figure out the distances to the two possible values, ceiling and floor. 10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We then go for the diff that is smaller. Only if they are equal does the 10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // mode matter. 10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double ceil = Math.ceil(div); 10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double ceildiff = ceil - div; // (ceil * roundingInc) - number; 10317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double floor = Math.floor(div); 10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double floordiff = div - floor; // number - (floor * roundingInc); 10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note that the diff values were those mapped back to the "normal" space by 10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // using the roundingInc. I don't have access to the original author of the 10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // code but suspect that that was to produce better result in edge cases 10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // because of machine precision, rather than simply using the difference 10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // between, say, ceil and div. However, it didn't work in all cases. Am 10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // trying instead using an epsilon value. 10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (mode) { 10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_HALF_EVEN: 10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We should be able to just return Math.rint(a), but this 10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // doesn't work in some VMs. 10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if one is smaller than the other, take the corresponding side 10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (floordiff + epsilon < ceildiff) { 10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = floor; 10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ceildiff + epsilon < floordiff) { 10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = ceil; 10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { // they are equal, so we want to round to whichever is even 10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double testFloor = floor / 2; 10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = (testFloor == Math.floor(testFloor)) ? floor : ceil; 10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_HALF_DOWN: 10567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = ((floordiff <= ceildiff + epsilon) ? floor : ceil); 10577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case BigDecimal.ROUND_HALF_UP: 10597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert div = ((ceildiff <= floordiff + epsilon) ? ceil : floor); 10607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 10617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert default: 10627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Invalid rounding mode: " + mode); 10637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = roundingIncReciprocal == 0.0 ? div * roundingInc : div / roundingIncReciprocal; 10667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return number; 10677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static double epsilon = 0.00000000001; 10707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 10727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 10737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 10747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Delegate to format_long_StringBuffer_FieldPosition_boolean 10757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 10767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) { 10777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(number, result, fieldPosition, false); 10787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition, 10817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 10827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(0); 10837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(0); 10847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we are to do rounding, we need to move into the BigDecimal 10867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // domain in order to do divide/multiply correctly. 10877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (actualRoundingIncrementICU != null) { 10887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(BigDecimal.valueOf(number), result, fieldPosition); 10897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 10907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative = (number < 0); 10927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isNegative) 10937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = -number; 10947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 10957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // In general, long values always represent real finite numbers, so we don't have 10967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to check for +/- Infinity or NaN. However, there is one case we have to be 10977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // careful of: The multiplier can push a number near MIN_VALUE or MAX_VALUE 10987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // outside the legal range. We check for this before multiplying, and if it 10997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // happens we use BigInteger instead. 11007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (multiplier != 1) { 11017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean tooBig = false; 11027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (number < 0) { // This can only happen if number == Long.MIN_VALUE 11037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long cutoff = Long.MIN_VALUE / multiplier; 11047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tooBig = (number <= cutoff); // number == cutoff can only happen if multiplier == -1 11057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 11067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long cutoff = Long.MAX_VALUE / multiplier; 11077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tooBig = (number > cutoff); 11087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tooBig) { 11107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Use 11117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // format_BigInteger_StringBuffer_FieldPosition_boolean instead 11127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // parseAttr is used to judge whether to synthesize attributes. 11137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(BigInteger.valueOf(isNegative ? -number : number), result, 11147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition, parseAttr); 11157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number *= multiplier; 11197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (digitList) { 11207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.set(number, precision(true)); 11217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(number, result, fieldPosition, isNegative, true, parseAttr); 11227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a BigInteger number. 11277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 11287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 11297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 11317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(BigInteger number, StringBuffer result, 11327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition) { 11337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(number, result, fieldPosition, false); 11347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition, 11377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 11387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we are to do rounding, we need to move into the BigDecimal 11397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // domain in order to do divide/multiply correctly. 11407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (actualRoundingIncrementICU != null) { 11417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(new BigDecimal(number), result, fieldPosition); 11427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (multiplier != 1) { 11457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = number.multiply(BigInteger.valueOf(multiplier)); 11467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // At this point we are guaranteed a nonnegative finite 11497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // number. 11507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (digitList) { 11517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.set(number, precision(true)); 11527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true, 11537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseAttr); 11547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a BigDecimal number. 11597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 11607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 11617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 11637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(java.math.BigDecimal number, StringBuffer result, 11647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition) { 11657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(number, result, fieldPosition, false); 11667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer format(java.math.BigDecimal number, StringBuffer result, 11697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition, 11707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 11717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (multiplier != 1) { 11727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = number.multiply(java.math.BigDecimal.valueOf(multiplier)); 11737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (actualRoundingIncrement != null) { 11767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = number.divide(actualRoundingIncrement, 0, roundingMode).multiply(actualRoundingIncrement); 11777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (digitList) { 11807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.set(number, precision(false), !useExponentialNotation && 11817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert !areSignificantDigitsUsed()); 11827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0, 11837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert false, parseAttr); 11847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 11867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 11877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 11887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a BigDecimal number. 11897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 11907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 11917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 11927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 11937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(BigDecimal number, StringBuffer result, 11947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition) { 11957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This method is just a copy of the corresponding java.math.BigDecimal method 11967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for now. It isn't very efficient since it must create a conversion object to 11977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do math on the rounding increment. In the future we may try to clean this up, 11987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // or even better, limit our support to just one flavor of BigDecimal. 11997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (multiplier != 1) { 12007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = number.multiply(BigDecimal.valueOf(multiplier), mathContext); 12017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (actualRoundingIncrementICU != null) { 12047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert number = number.divide(actualRoundingIncrementICU, 0, roundingMode) 12057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert .multiply(actualRoundingIncrementICU, mathContext); 12067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert synchronized (digitList) { 12097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.set(number, precision(false), !useExponentialNotation && 12107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert !areSignificantDigitsUsed()); 12117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0, 12127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert false, false); 12137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns true if a grouping separator belongs at the given position, based on whether 12187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * grouping is in use and the values of the primary and secondary grouping interval. 12197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 12207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos the number of integer digits to the right of the current position. Zero 12217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * indicates the position after the rightmost integer digit. 12227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if a grouping character belongs at the current position. 12237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean isGroupingPosition(int pos) { 12257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean result = false; 12267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) { 12277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((groupingSize2 > 0) && (pos > groupingSize)) { 12287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = ((pos - groupingSize) % groupingSize2) == 0; 12297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 12307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = pos % groupingSize == 0; 12317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 12347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return the number of fraction digits to display, or the total 12387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number of digits for significant digit formats and exponential 12397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formats. 12407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int precision(boolean isIntegral) { 12427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (areSignificantDigitsUsed()) { 12437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getMaximumSignificantDigits(); 12447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (useExponentialNotation) { 12457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getMinimumIntegerDigits() + getMaximumFractionDigits(); 12467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 12477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return isIntegral ? 0 : getMaximumFractionDigits(); 12487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer subformat(int number, StringBuffer result, FieldPosition fieldPosition, 12527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative, boolean isInteger, boolean parseAttr) { 12537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 12547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // compute the plural category from the digitList plus other settings 12557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(currencyPluralInfo.select(getFixedDecimal(number)), 12567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result, fieldPosition, isNegative, 12577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isInteger, parseAttr); 12587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 12597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(result, fieldPosition, isNegative, isInteger, parseAttr); 12607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 12647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This is ugly, but don't see a better way to do it without major restructuring of the code. 12657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 12667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*package*/ FixedDecimal getFixedDecimal(double number) { 12677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // get the visible fractions and the number of fraction digits. 12687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return getFixedDecimal(number, digitList); 12697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 12717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FixedDecimal getFixedDecimal(double number, DigitList dl) { 12727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fractionalDigitsInDigitList = dl.count - dl.decimalAt; 12737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int v; 12747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long f; 12757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxFractionalDigits; 12767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minFractionalDigits; 12777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSignificantDigits) { 12787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxFractionalDigits = maxSignificantDigits - dl.decimalAt; 12797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minFractionalDigits = minSignificantDigits - dl.decimalAt; 12807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (minFractionalDigits < 0) { 12817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minFractionalDigits = 0; 12827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxFractionalDigits < 0) { 12847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxFractionalDigits = 0; 12857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 12877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxFractionalDigits = getMaximumFractionDigits(); 12887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minFractionalDigits = getMinimumFractionDigits(); 12897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert v = fractionalDigitsInDigitList; 12917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (v < minFractionalDigits) { 12927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert v = minFractionalDigits; 12937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (v > maxFractionalDigits) { 12947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert v = maxFractionalDigits; 12957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 12967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert f = 0; 12977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (v > 0) { 12987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = Math.max(0, dl.decimalAt); i < dl.count; ++i) { 12997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert f *= 10; 13007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert f += (dl.digits[i] - '0'); 13017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = v; i < fractionalDigitsInDigitList; ++i) { 13037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert f *= 10; 13047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new FixedDecimal(number, v, f); 13077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer subformat(double number, StringBuffer result, FieldPosition fieldPosition, 13107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative, 13117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isInteger, boolean parseAttr) { 13127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 13137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // compute the plural category from the digitList plus other settings 13147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(currencyPluralInfo.select(getFixedDecimal(number)), 13157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result, fieldPosition, isNegative, 13167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isInteger, parseAttr); 13177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 13187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(result, fieldPosition, isNegative, isInteger, parseAttr); 13197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer subformat(String pluralCount, StringBuffer result, FieldPosition fieldPosition, 13237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative, boolean isInteger, boolean parseAttr) { 13247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // There are 2 ways to activate currency plural format: by applying a pattern with 13257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 3 currency sign directly, or by instantiate a decimal formatter using 13267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // PLURALCURRENCYSTYLE. For both cases, the number of currency sign in the 13277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern is 3. Even if the number of currency sign in the pattern is 3, it does 13287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not mean we need to reset the pattern. For 1st case, we do not need to reset 13297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern. For 2nd case, we might need to reset pattern, if the default pattern 13307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (corresponding to plural count 'other') we use is different from the pattern 13317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // based on 'pluralCount'. 13327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 13337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // style is only valid when decimal formatter is constructed through 13347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DecimalFormat(pattern, symbol, style) 13357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (style == NumberFormat.PLURALCURRENCYSTYLE) { 13367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // May need to reset pattern if the style is PLURALCURRENCYSTYLE. 13377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String currencyPluralPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount); 13387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatPattern.equals(currencyPluralPattern) == false) { 13397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(currencyPluralPattern, false); 13407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Expand the affix to the right name according to the plural rule. This is only 13437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // used for currency plural formatting. Currency plural name is not a fixed 13447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // static one, it is a dynamic name based on the currency plural count. So, the 13457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // affixes need to be expanded here. For other cases, the affix is a static one 13467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // based on pattern alone, and it is already expanded during applying pattern, or 13477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // setDecimalFormatSymbols, or setCurrency. 13487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixAdjustWidth(pluralCount); 13497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return subformat(result, fieldPosition, isNegative, isInteger, parseAttr); 13507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 13537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Complete the formatting of a finite number. On entry, the 13547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digitList must be filled in with the correct digits. 13557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 13567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition, 13577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isNegative, boolean isInteger, boolean parseAttr) { 13587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // NOTE: This isn't required anymore because DigitList takes care of this. 13597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 13607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // // The negative of the exponent represents the number of leading // zeros 13617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // between the decimal and the first non-zero digit, for // a value < 0.1 (e.g., 13627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for 0.00123, -fExponent == 2). If this // is more than the maximum fraction 13637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits, then we have an underflow // for the printed representation. We 13647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // recognize this here and set // the DigitList representation to zero in this 13657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // situation. 13667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 13677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if (-digitList.decimalAt >= getMaximumFractionDigits()) 13687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // { 13697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digitList.count = 0; 13707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // } 13717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Per bug 4147706, DecimalFormat must respect the sign of numbers which format as 13757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // zero. This allows sensible computations and preserves relations such as 13767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // signum(1/x) = signum(x), where x is +Infinity or -Infinity. Prior to this fix, 13777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we always formatted zero values as if they were positive. Liu 7/6/98. 13787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitList.isZero()) { 13797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.decimalAt = 0; // Normalize 13807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int prefixLen = appendAffix(result, isNegative, true, parseAttr); 13837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useExponentialNotation) { 13857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subformatExponential(result, fieldPosition, parseAttr); 13867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 13877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subformatFixed(result, fieldPosition, isInteger, parseAttr); 13887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int suffixLen = appendAffix(result, isNegative, false, parseAttr); 13917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addPadding(result, fieldPosition, prefixLen, suffixLen); 13937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 13947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 13957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 13967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void subformatFixed(StringBuffer result, 13977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition, 13987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isInteger, 13997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 14007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char [] digits = symbols.getDigitsLocal(); 14017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char grouping = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ? 14037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getGroupingSeparator(): symbols.getMonetaryGroupingSeparator(); 14047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ? 14057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator(); 14067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useSigDig = areSignificantDigitsUsed(); 14077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxIntDig = getMaximumIntegerDigits(); 14087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minIntDig = getMinimumIntegerDigits(); 14097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i; 14107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Record the integer start index. 14117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int intBegin = result.length(); 14127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 14137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 14147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 14157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 14167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 14177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long fractionalDigits = 0; 14197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fractionalDigitsCount = 0; 14207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean recordFractionDigits = false; 14217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int sigCount = 0; 14237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minSigDig = getMinimumSignificantDigits(); 14247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxSigDig = getMaximumSignificantDigits(); 14257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useSigDig) { 14267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minSigDig = 0; 14277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxSigDig = Integer.MAX_VALUE; 14287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output the integer portion. Here 'count' is the total number of integer 14317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits we will display, including both leading zeros required to satisfy 14327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // getMinimumIntegerDigits, and actual digits present in the number. 14337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = useSigDig ? Math.max(1, digitList.decimalAt) : minIntDig; 14347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitList.decimalAt > 0 && count < digitList.decimalAt) { 14357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = digitList.decimalAt; 14367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle the case where getMaximumIntegerDigits() is smaller than the real 14397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // number of integer digits. If this is so, we output the least significant 14407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // max integer digits. For example, the value 1997 printed with 2 max integer 14417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits is just "97". 14427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digitIndex = 0; // Index into digitList.fDigits[] 14447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (count > maxIntDig && maxIntDig >= 0) { 14457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = maxIntDig; 14467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitIndex = digitList.decimalAt - count; 14477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int sizeBeforeIntegerPart = result.length(); 14507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = count - 1; i >= 0; --i) { 14517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i < digitList.decimalAt && digitIndex < digitList.count 14527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && sigCount < maxSigDig) { 14537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output a real digit 14547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[digitList.getDigitValue(digitIndex++)]); 14557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++sigCount; 14567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 14577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output a zero (leading or trailing) 14587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[0]); 14597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (sigCount > 0) { 14607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++sigCount; 14617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output grouping separator if necessary. 14657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isGroupingPosition(i)) { 14667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(grouping); 14677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add grouping separator attribute here. 14687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 14697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Length of grouping separator is 1. 14707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length()); 14717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 14767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 14777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 14787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 14797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 14807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This handles the special case of formatting 0. For zero only, we count the 14837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // zero to the left of the decimal point as one signficant digit. Ordinarily we 14847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // do not count any leading 0's as significant. If the number we are formatting 14857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is not zero, then either sigCount or digits.getCount() will be non-zero. 14867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (sigCount == 0 && digitList.count == 0) { 14877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sigCount = 1; 14887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 14897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Determine whether or not there are any printable fractional digits. If 14917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we've used up the digits we know there aren't. 14927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean fractionPresent = (!isInteger && digitIndex < digitList.count) 14937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0)); 14947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 14957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If there is no fraction present, and we haven't printed any integer digits, 14967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // then print a zero. Otherwise we won't print _any_ digits, and we won't be 14977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // able to parse this string. 14987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!fractionPresent && result.length() == sizeBeforeIntegerPart) 14997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[0]); 15007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for integer part. 15017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 15027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.INTEGER, intBegin, result.length()); 15037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output the decimal separator if we always do so. 15057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (decimalSeparatorAlwaysShown || fractionPresent) { 15067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) { 15077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 15087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(decimal); 15107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) { 15117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 15127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for decimal separator 15147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 15157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.DECIMAL_SEPARATOR, result.length() - 1, result.length()); 15167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 15207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 15217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 15227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) { 15237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 15247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Record the begin index of fraction part. 15277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fracBegin = result.length(); 15287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert recordFractionDigits = fieldPosition instanceof UFieldPosition; 15297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits(); 15317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig && (sigCount == maxSigDig || 15327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (sigCount >= minSigDig && digitIndex == digitList.count))) { 15337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count = 0; 15347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < count; ++i) { 15367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Here is where we escape from the loop. We escape if we've output the 15377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // maximum fraction digits (specified in the for expression above). We 15387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // also stop when we've output the minimum digits and either: we have an 15397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // integer, so there is no fractional stuff to display, or we're out of 15407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // significant digits. 15417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useSigDig && i >= getMinimumFractionDigits() && 15427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (isInteger || digitIndex >= digitList.count)) { 15437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 15447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output leading fractional zeros. These are zeros that come after the 15477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // decimal but before any significant digits. These are only output if 15487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // abs(number being formatted) < 1.0. 15497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (-1 - i > (digitList.decimalAt - 1)) { 15507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[0]); 15517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recordFractionDigits) { 15527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++fractionalDigitsCount; 15537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fractionalDigits *= 10; 15547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 15567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Output a digit, if we have any precision left, or a zero if we 15597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // don't. We don't want to output noise digits. 15607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isInteger && digitIndex < digitList.count) { 15617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert byte digit = digitList.getDigitValue(digitIndex++); 15627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[digit]); 15637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recordFractionDigits) { 15647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++fractionalDigitsCount; 15657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fractionalDigits *= 10; 15667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fractionalDigits += digit; 15677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 15697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[0]); 15707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recordFractionDigits) { 15717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++fractionalDigitsCount; 15727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fractionalDigits *= 10; 15737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we reach the maximum number of significant digits, or if we output 15777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // all the real digits and reach the minimum, then we are done. 15787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++sigCount; 15797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig && (sigCount == maxSigDig || 15807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (digitIndex == digitList.count && sigCount >= minSigDig))) { 15817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 15827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 15867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 15877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 15887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) { 15897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 15907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recordFractionDigits) { 15927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits); 15937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 15957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute information if necessary. 15967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr && (decimalSeparatorAlwaysShown || fractionPresent)) { 15977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.FRACTION, fracBegin, result.length()); 15987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 15997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void subformatExponential(StringBuffer result, 16027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition fieldPosition, 16037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 16047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char [] digits = symbols.getDigitsLocal(); 16057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ? 16067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator(); 16077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useSigDig = areSignificantDigitsUsed(); 16087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxIntDig = getMaximumIntegerDigits(); 16097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minIntDig = getMinimumIntegerDigits(); 16107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i; 16117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 16127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 16137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 16147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(-1); 16157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 16167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(-1); 16177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 16187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 16197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(-1); 16207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) { 16217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(-1); 16227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] 16267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the begin index of integer part 16277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the end index of integer part 16287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the begin index of fractional part 16297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int intBegin = result.length(); 16307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int intEnd = -1; 16317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fracBegin = -1; 16327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minFracDig = 0; 16337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig) { 16347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxIntDig = minIntDig = 1; 16357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minFracDig = getMinimumSignificantDigits() - 1; 16367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minFracDig = getMinimumFractionDigits(); 16387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) { 16397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxIntDig = 1; 16407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxIntDig < minIntDig) { 16417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxIntDig = minIntDig; 16427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxIntDig > minIntDig) { 16457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minIntDig = 1; 16467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long fractionalDigits = 0; 16497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int fractionalDigitsCount = 0; 16507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean recordFractionDigits = false; 16517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Minimum integer digits are handled in exponential format by adjusting the 16537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // exponent. For example, 0.01234 with 3 minimum integer digits is "123.4E-4". 16547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Maximum integer digits are interpreted as indicating the repeating 16567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // range. This is useful for engineering notation, in which the exponent is 16577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // restricted to a multiple of 3. For example, 0.01234 with 3 maximum integer 16587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits is "12.34e-3". If maximum integer digits are defined and are larger 16597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // than minimum integer digits, then minimum integer digits are ignored. 16607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int exponent = digitList.decimalAt; 16627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxIntDig > 1 && maxIntDig != minIntDig) { 16637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // A exponent increment is defined; adjust to it. 16647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = (exponent > 0) ? (exponent - 1) / maxIntDig : (exponent / maxIntDig) - 1; 16657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent *= maxIntDig; 16667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 16677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // No exponent increment is defined; use minimum integer digits. 16687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If none is specified, as in "#E0", generate 1 integer digit. 16697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent -= (minIntDig > 0 || minFracDig > 0) ? minIntDig : 1; 16707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We now output a minimum number of digits, and more if there are more 16737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits, up to the maximum number of digits. We place the decimal point 16747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // after the "integer" digits, which are the first (decimalAt - exponent) 16757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits. 16767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minimumDigits = minIntDig + minFracDig; 16777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The number of integer digits is handled specially if the number 16787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is zero, since then there may be no digits. 16797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int integerDigits = digitList.isZero() ? minIntDig : digitList.decimalAt - exponent; 16807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int totalDigits = digitList.count; 16817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (minimumDigits > totalDigits) 16827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert totalDigits = minimumDigits; 16837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (integerDigits > totalDigits) 16847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert totalDigits = integerDigits; 16857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < totalDigits; ++i) { 16877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i == integerDigits) { 16887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 16897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 16907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 16917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 16927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 16937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 16947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 16957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for integer part 16967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 16977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intEnd = result.length(); 16987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.INTEGER, intBegin, result.length()); 16997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(decimal); 17017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for decimal separator 17027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 17037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Length of decimal separator is 1. 17047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int decimalSeparatorBegin = result.length() - 1; 17057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin, 17067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.length()); 17077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fracBegin = result.length(); 17087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information for caller. 17107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 17117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 17127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) { 17137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 17147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert recordFractionDigits = fieldPosition instanceof UFieldPosition; 17167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert byte digit = (i < digitList.count) ? digitList.getDigitValue(i) : (byte)0; 17197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[digit]); 17207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recordFractionDigits) { 17217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++fractionalDigitsCount; 17227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fractionalDigits *= 10; 17237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fractionalDigits += digit; 17247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For ICU compatibility and format 0 to 0E0 with pattern "#E0" [Richard/GCL] 17287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitList.isZero() && (totalDigits == 0)) { 17297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[0]); 17307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Record field information 17337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 17347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getEndIndex() < 0) { 17357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 17367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 17387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getBeginIndex() < 0) { 17397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 17407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 17427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) { 17437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getEndIndex() < 0) { 17447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 17457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.FRACTION) { 17477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fieldPosition.getBeginIndex() < 0) { 17487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(result.length()); 17497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(result.length()); 17517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (recordFractionDigits) { 17537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits); 17547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Calcuate the end index of integer part and fractional 17577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // part if they are not properly processed yet. 17587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 17597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (intEnd < 0) { 17607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.INTEGER, intBegin, result.length()); 17617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (fracBegin > 0) { 17637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.FRACTION, fracBegin, result.length()); 17647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The exponent is output using the pattern-specified minimum exponent 17687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits. There is no maximum limit to the exponent digits, since truncating 17697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the exponent would result in an unacceptable inaccuracy. 17707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(symbols.getExponentSeparator()); 17717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] For exponent symbol, add an attribute. 17727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 17737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.EXPONENT_SYMBOL, result.length() - 17747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getExponentSeparator().length(), result.length()); 17757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For zero values, we force the exponent to zero. We must do this here, and 17777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not earlier, because the value is used to determine integer digit count 17787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // above. 17797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitList.isZero()) 17807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = 0; 17817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 17827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean negativeExponent = exponent < 0; 17837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negativeExponent) { 17847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = -exponent; 17853937b302ef4bb23600d398d228736895b6bbb314Travis Keep result.append(symbols.getMinusString()); 17867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] If exponent has sign, then add an exponent sign 17877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // attribute. 17887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 17897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Length of exponent sign is 1. 17907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length()); 17917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 17927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (exponentSignAlwaysShown) { 17933937b302ef4bb23600d398d228736895b6bbb314Travis Keep result.append(symbols.getPlusString()); 17947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add an plus sign attribute. 17957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 17967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Length of exponent sign is 1. 17977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int expSignBegin = result.length() - 1; 17987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.EXPONENT_SIGN, expSignBegin, result.length()); 17997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int expBegin = result.length(); 18027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList.set(exponent); 18037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 18047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int expDig = minExponentDigits; 18057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useExponentialNotation && expDig < 1) { 18067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expDig = 1; 18077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = digitList.decimalAt; i < expDig; ++i) 18097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(digits[0]); 18107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < digitList.decimalAt; ++i) { 18127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append((i < digitList.count) ? digits[digitList.getDigitValue(i)] 18137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : digits[0]); 18147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Add attribute for exponent part. 18167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 18177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.EXPONENT, expBegin, result.length()); 18187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final void addPadding(StringBuffer result, FieldPosition fieldPosition, int prefixLen, 18227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int suffixLen) { 18237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0) { 18247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int len = formatWidth - result.length(); 18257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (len > 0) { 18267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] padding = new char[len]; 18277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < len; ++i) { 18287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padding[i] = pad; 18297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (padPosition) { 18317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PAD_AFTER_PREFIX: 18327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.insert(prefixLen, padding); 18337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PAD_BEFORE_PREFIX: 18357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.insert(0, padding); 18367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PAD_BEFORE_SUFFIX: 18387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.insert(result.length() - suffixLen, padding); 18397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PAD_AFTER_SUFFIX: 18417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(padding); 18427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 18437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX) { 18457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len); 18467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len); 18477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 18537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parses the given string, returning a <code>Number</code> object to represent the 18547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsed value. <code>Double</code> objects are returned to represent non-integral 18557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * values which cannot be stored in a <code>BigDecimal</code>. These are 18567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>NaN</code>, infinity, -infinity, and -0.0. If {@link #isParseBigDecimal()} is 18577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * false (the default), all other values are returned as <code>Long</code>, 18587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigInteger</code>, or <code>BigDecimal</code> values, in that order of 18597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * preference. If {@link #isParseBigDecimal()} is true, all other values are returned 18607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * as <code>BigDecimal</code> valuse. If the parse fails, null is returned. 18617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 18627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the string to be parsed 18637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param parsePosition defines the position where parsing is to begin, and upon 18647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return, the position where parsing left off. If the position has not changed upon 18657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return, then parsing failed. 18667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a <code>Number</code> object with the parsed value or 18677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>null</code> if the parse failed 18687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 18697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 18707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 18717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Number parse(String text, ParsePosition parsePosition) { 18727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (Number) parse(text, parsePosition, null); 18737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 18767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parses text from the given string as a CurrencyAmount. Unlike the parse() method, 18777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this method will attempt to parse a generic currency name, searching for a match of 18787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this object's locale's currency display names, or for a 3-letter ISO currency 18797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * code. This method will fail if this format is not a currency format, that is, if it 18807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * does not contain the currency pattern symbol (U+00A4) in its prefix or suffix. 18817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 18827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the text to parse 18837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos input-output position; on input, the position within text to match; must 18847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * have 0 <= pos.getIndex() < text.length(); on output, the position after the last 18857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * matched character. If the parse fails, the position in unchanged upon output. 18867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a CurrencyAmount, or null upon failure 18877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 49 18887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 18897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 18907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public CurrencyAmount parseCurrency(CharSequence text, ParsePosition pos) { 18917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency[] currency = new Currency[1]; 18927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (CurrencyAmount) parse(text.toString(), pos, currency); 18937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 18947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 18957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 18967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parses the given text as either a Number or a CurrencyAmount. 18977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 18987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the string to parse 18997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param parsePosition input-output position; on input, the position within text to 19007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * match; must have 0 <= pos.getIndex() < text.length(); on output, the position after 19017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the last matched character. If the parse fails, the position in unchanged upon 19027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * output. 19037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param currency if non-null, a CurrencyAmount is parsed and returned; otherwise a 19047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Number is parsed and returned 19057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return a Number or CurrencyAmount or null 19067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 19077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Object parse(String text, ParsePosition parsePosition, Currency[] currency) { 19087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int backup; 19097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = backup = parsePosition.getIndex(); 19107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle NaN as a special case: 19127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Skip padding characters, if around prefix 19147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0 && 19157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (padPosition == PAD_BEFORE_PREFIX || padPosition == PAD_AFTER_PREFIX)) { 19167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = skipPadding(text, i); 19177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text.regionMatches(i, symbols.getNaN(), 0, symbols.getNaN().length())) { 19197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i += symbols.getNaN().length(); 19207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Skip padding characters, if around suffix 19217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX || 19227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPosition == PAD_AFTER_SUFFIX)) { 19237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = skipPadding(text, i); 19247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(i); 19267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new Double(Double.NaN); 19277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // NaN parse failed; start over 19307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = backup; 19317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] status = new boolean[STATUS_LENGTH]; 19337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) { 19347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!parseForCurrency(text, parsePosition, currency, status)) { 19357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 19367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!subparse(text, parsePosition, digitList, status, currency, negPrefixPattern, 19397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negSuffixPattern, posPrefixPattern, posSuffixPattern, 19407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert false, Currency.SYMBOL_NAME)) { 19417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(backup); 19427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 19437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Number n = null; 19477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle infinity 19497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (status[STATUS_INFINITE]) { 19507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = new Double(status[STATUS_POSITIVE] ? Double.POSITIVE_INFINITY : 19517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Double.NEGATIVE_INFINITY); 19527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle underflow 19557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if (status[STATUS_UNDERFLOW]) { 19567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = status[STATUS_POSITIVE] ? new Double("0.0") : new Double("-0.0"); 19577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle -0.0 19607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else if (!status[STATUS_POSITIVE] && digitList.isZero()) { 19617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = new Double("-0.0"); 19627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 19657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do as much of the multiplier conversion as possible without 19667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // losing accuracy. 19677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int mult = multiplier; // Don't modify this.multiplier 19687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (mult % 10 == 0) { 19697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --digitList.decimalAt; 19707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert mult /= 10; 19717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 19737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle integral values 19747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) { 19757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // hack quick long 19767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitList.decimalAt < 12) { // quick check for long 19777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long l = 0; 19787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitList.count > 0) { 19797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int nx = 0; 19807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (nx < digitList.count) { 19817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert l = l * 10 + (char) digitList.digits[nx++] - '0'; 19827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (nx++ < digitList.decimalAt) { 19847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert l *= 10; 19857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!status[STATUS_POSITIVE]) { 19877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert l = -l; 19887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = Long.valueOf(l); 19917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 19927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]); 19937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = (big.bitLength() < 64) ? (Number) Long.valueOf(big.longValue()) : (Number) big; 19947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 19967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle non-integral values or the case where parseBigDecimal is set 19977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 19987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]); 19997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = big; 20007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (mult != 1) { 20017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert n = big.divide(BigDecimal.valueOf(mult), mathContext); 20027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Assemble into CurrencyAmount if necessary 20077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (currency != null) ? (Object) new CurrencyAmount(n, currency[0]) : (Object) n; 20087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean parseForCurrency(String text, ParsePosition parsePosition, 20117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency[] currency, boolean[] status) { 20127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int origPos = parsePosition.getIndex(); 20137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isReadyForParsing) { 20147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int savedCurrencySignCount = currencySignCount; 20157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setupCurrencyAffixForAllPatterns(); 20167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // reset pattern back 20177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (savedCurrencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 20187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(formatPattern, false); 20197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(formatPattern, false); 20217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isReadyForParsing = true; 20237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxPosIndex = origPos; 20257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxErrorPos = -1; 20267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] savedStatus = null; 20277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // First, parse against current pattern. 20287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Since current pattern could be set by applyPattern(), 20297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // it could be an arbitrary pattern, and it may not be the one 20307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // defined in current locale. 20317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] tmpStatus = new boolean[STATUS_LENGTH]; 20327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ParsePosition tmpPos = new ParsePosition(origPos); 20337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DigitList tmpDigitList = new DigitList(); 20347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean found; 20357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (style == NumberFormat.PLURALCURRENCYSTYLE) { 20367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency, 20377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern, 20387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert true, Currency.LONG_NAME); 20397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert found = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency, 20417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern, 20427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert true, Currency.SYMBOL_NAME); 20437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (found) { 20457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tmpPos.getIndex() > maxPosIndex) { 20467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxPosIndex = tmpPos.getIndex(); 20477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert savedStatus = tmpStatus; 20487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList = tmpDigitList; 20497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxErrorPos = tmpPos.getErrorIndex(); 20527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Then, parse against affix patterns. Those are currency patterns and currency 20547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // plural patterns defined in the locale. 20557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (AffixForCurrency affix : affixPatternsForCurrency) { 20567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpStatus = new boolean[STATUS_LENGTH]; 20577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpPos = new ParsePosition(origPos); 20587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpDigitList = new DigitList(); 20597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency, 20607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.getNegPrefix(), affix.getNegSuffix(), 20617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.getPosPrefix(), affix.getPosSuffix(), 20627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert true, affix.getPatternType()); 20637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (result) { 20647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert found = true; 20657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tmpPos.getIndex() > maxPosIndex) { 20667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxPosIndex = tmpPos.getIndex(); 20677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert savedStatus = tmpStatus; 20687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList = tmpDigitList; 20697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 20717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() 20727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : maxErrorPos; 20737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 20757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Finally, parse against simple affix to find the match. For example, in 20767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TestMonster suite, if the to-be-parsed text is "-\u00A40,00". 20777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // complexAffixCompare will not find match, since there is no ISO code matches 20787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "\u00A4", and the parse stops at "\u00A4". We will just use simple affix 20797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // comparison (look for exact match) to pass it. 20807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 20817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO: We should parse against simple affix first when 20827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // output currency is not requested. After the complex currency 20837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // parsing implementation was introduced, the default currency 20847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // instance parsing slowed down because of the new code flow. 20857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // I filed #10312 - Yoshito 20867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpStatus = new boolean[STATUS_LENGTH]; 20877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpPos = new ParsePosition(origPos); 20887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert tmpDigitList = new DigitList(); 20897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 20907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Disable complex currency parsing and try it again. 20917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean result = subparse(text, tmpPos, tmpDigitList, tmpStatus, currency, 20927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negativePrefix, negativeSuffix, positivePrefix, positiveSuffix, 20937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert false /* disable complex currency parsing */, Currency.SYMBOL_NAME); 20947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (result) { 20957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (tmpPos.getIndex() > maxPosIndex) { 20967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxPosIndex = tmpPos.getIndex(); 20977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert savedStatus = tmpStatus; 20987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList = tmpDigitList; 20997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert found = true; 21017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 21027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? tmpPos.getErrorIndex() : 21037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxErrorPos; 21047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!found) { 21077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // parsePosition.setIndex(origPos); 21087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(maxErrorPos); 21097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 21107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(maxPosIndex); 21117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(-1); 21127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int index = 0; index < STATUS_LENGTH; ++index) { 21137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[index] = savedStatus[index]; 21147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return found; 21177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Get affix patterns used in locale's currency pattern (NumberPatterns[1]) and 21207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // currency plural pattern (CurrencyUnitPatterns). 21217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setupCurrencyAffixForAllPatterns() { 21227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencyPluralInfo == null) { 21237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale()); 21247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPatternsForCurrency = new HashSet<AffixForCurrency>(); 21267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // save the current pattern, since it will be changed by 21287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // applyPatternWithoutExpandAffix 21297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String savedFormatPattern = formatPattern; 21307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // CURRENCYSTYLE and ISOCURRENCYSTYLE should have the same prefix and suffix, so, 21327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // only need to save one of them. Here, chose onlyApplyPatternWithoutExpandAffix 21337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // without saving the actualy pattern in 'pattern' data member. TODO: is it uloc? 21347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(getPattern(symbols.getULocale(), NumberFormat.CURRENCYSTYLE), 21357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert false); 21367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert AffixForCurrency affixes = new AffixForCurrency( 21377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPattern, negSuffixPattern, posPrefixPattern, posSuffixPattern, 21387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency.SYMBOL_NAME); 21397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPatternsForCurrency.add(affixes); 21407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // add plural pattern 21427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Iterator<String> iter = currencyPluralInfo.pluralPatternIterator(); 21437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<String> currencyUnitPatternSet = new HashSet<String>(); 21447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (iter.hasNext()) { 21457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pluralCount = iter.next(); 21467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String currencyPattern = currencyPluralInfo.getCurrencyPluralPattern(pluralCount); 21477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencyPattern != null && 21487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyUnitPatternSet.contains(currencyPattern) == false) { 21497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyUnitPatternSet.add(currencyPattern); 21507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(currencyPattern, false); 21517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixes = new AffixForCurrency(negPrefixPattern, negSuffixPattern, posPrefixPattern, 21527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posSuffixPattern, Currency.LONG_NAME); 21537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPatternsForCurrency.add(affixes); 21547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // reset pattern back 21577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatPattern = savedFormatPattern; 21587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 21597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // currency formatting style options 21617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int CURRENCY_SIGN_COUNT_ZERO = 0; 21627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT = 1; 21637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int CURRENCY_SIGN_COUNT_IN_ISO_FORMAT = 2; 21647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT = 3; 21657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int STATUS_INFINITE = 0; 21677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int STATUS_POSITIVE = 1; 21687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int STATUS_UNDERFLOW = 2; 21697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final int STATUS_LENGTH = 3; 21707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final UnicodeSet dotEquivalents = new UnicodeSet( 21727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //"[.\u2024\u3002\uFE12\uFE52\uFF0E\uFF61]" 21737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002E, 0x002E, 21747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2024, 0x2024, 21757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x3002, 0x3002, 21767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE12, 0xFE12, 21777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE52, 0xFE52, 21787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0E, 0xFF0E, 21797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF61, 0xFF61).freeze(); 21807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final UnicodeSet commaEquivalents = new UnicodeSet( 21827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //"[,\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64]" 21837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002C, 0x002C, 21847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x060C, 0x060C, 21857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x066B, 0x066B, 21867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x3001, 0x3001, 21877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE10, 0xFE11, 21887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE50, 0xFE51, 21897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0C, 0xFF0C, 21907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF64, 0xFF64).freeze(); 21917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 21927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// private static final UnicodeSet otherGroupingSeparators = new UnicodeSet( 21937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]" 21947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x0020, 0x0020, 21957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x0027, 0x0027, 21967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x00A0, 0x00A0, 21977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x066C, 0x066C, 21987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x2000, 0x200A, 21997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x2018, 0x2019, 22007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x202F, 0x202F, 22017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x205F, 0x205F, 22027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x3000, 0x3000, 22037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0xFF07, 0xFF07).freeze(); 22047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final UnicodeSet strictDotEquivalents = new UnicodeSet( 22067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //"[.\u2024\uFE52\uFF0E\uFF61]" 22077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002E, 0x002E, 22087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2024, 0x2024, 22097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE52, 0xFE52, 22107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0E, 0xFF0E, 22117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF61, 0xFF61).freeze(); 22127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final UnicodeSet strictCommaEquivalents = new UnicodeSet( 22147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //"[,\u066B\uFE10\uFE50\uFF0C]" 22157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002C, 0x002C, 22167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x066B, 0x066B, 22177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE10, 0xFE10, 22187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE50, 0xFE50, 22197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0C, 0xFF0C).freeze(); 22207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// private static final UnicodeSet strictOtherGroupingSeparators = new UnicodeSet( 22227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// //"[\\ '\u00A0\u066C\u2000-\u200A\u2018\u2019\u202F\u205F\u3000\uFF07]" 22237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x0020, 0x0020, 22247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x0027, 0x0027, 22257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x00A0, 0x00A0, 22267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x066C, 0x066C, 22277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x2000, 0x200A, 22287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x2018, 0x2019, 22297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x202F, 0x202F, 22307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x205F, 0x205F, 22317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0x3000, 0x3000, 22327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// 0xFF07, 0xFF07).freeze(); 22337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final UnicodeSet defaultGroupingSeparators = 22357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // new UnicodeSet(dotEquivalents).addAll(commaEquivalents) 22367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // .addAll(otherGroupingSeparators).freeze(); 22377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new UnicodeSet( 22387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x0020, 0x0020, 22397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x0027, 0x0027, 22407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002C, 0x002C, 22417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002E, 0x002E, 22427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x00A0, 0x00A0, 22437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x060C, 0x060C, 22447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x066B, 0x066C, 22457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2000, 0x200A, 22467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2018, 0x2019, 22477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2024, 0x2024, 22487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x202F, 0x202F, 22497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x205F, 0x205F, 22507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x3000, 0x3002, 22517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE10, 0xFE12, 22527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE50, 0xFE52, 22537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF07, 0xFF07, 22547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0C, 0xFF0C, 22557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0E, 0xFF0E, 22567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF61, 0xFF61, 22577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF64, 0xFF64).freeze(); 22587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final UnicodeSet strictDefaultGroupingSeparators = 22607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // new UnicodeSet(strictDotEquivalents).addAll(strictCommaEquivalents) 22617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // .addAll(strictOtherGroupingSeparators).freeze(); 22627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new UnicodeSet( 22637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x0020, 0x0020, 22647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x0027, 0x0027, 22657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002C, 0x002C, 22667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002E, 0x002E, 22677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x00A0, 0x00A0, 22687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x066B, 0x066C, 22697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2000, 0x200A, 22707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2018, 0x2019, 22717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2024, 0x2024, 22727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x202F, 0x202F, 22737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x205F, 0x205F, 22747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x3000, 0x3000, 22757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE10, 0xFE10, 22767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE50, 0xFE50, 22777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE52, 0xFE52, 22787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF07, 0xFF07, 22797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0C, 0xFF0C, 22807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0E, 0xFF0E, 22817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF61, 0xFF61).freeze(); 22827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final UnicodeSet minusSigns = 22847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new UnicodeSet( 22857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002D, 0x002D, 22867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x207B, 0x207B, 22877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x208B, 0x208B, 22887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2212, 0x2212, 22897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2796, 0x2796, 22907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE63, 0xFE63, 22917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0D, 0xFF0D).freeze(); 22927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 22937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final UnicodeSet plusSigns = 22947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new UnicodeSet( 22957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x002B, 0x002B, 22967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x207A, 0x207A, 22977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x208A, 0x208A, 22987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0x2795, 0x2795, 22997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFB29, 0xFB29, 23007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFE62, 0xFE62, 23017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 0xFF0B, 0xFF0B).freeze(); 23027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // equivalent grouping and decimal support 23047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final boolean skipExtendedSeparatorParsing = ICUConfig.get( 23057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false") 23067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert .equals("true"); 23077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // allow control of requiring a matching decimal point when parsing 23097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseRequireDecimalPoint = false; 23107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // When parsing a number with big exponential value, it requires to transform the 23127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // value into a string representation to construct BigInteger instance. We want to 23137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // set the maximum size because it can easily trigger OutOfMemoryException. 23147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // PARSE_MAX_EXPONENT is currently set to 1000 (See getParseMaxDigits()), 23157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // which is much bigger than MAX_VALUE of Double ( See the problem reported by ticket#5698 23167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int PARSE_MAX_EXPONENT = 1000; 23177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 23197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Parses the given text into a number. The text is parsed beginning at parsePosition, 23207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * until an unparseable character is seen. 23217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 23227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the string to parse. 23237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param parsePosition the position at which to being parsing. Upon return, the first 23247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * unparseable character. 23257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param digits the DigitList to set to the parsed value. 23267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param status Upon return contains boolean status flags indicating whether the 23277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value was infinite and whether it was positive. 23287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param currency return value for parsed currency, for generic currency parsing 23297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * mode, or null for normal parsing. In generic currency parsing mode, any currency is 23307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsed, not just the currency that this formatter is set to. 23317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param negPrefix negative prefix pattern 23327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param negSuffix negative suffix pattern 23337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param posPrefix positive prefix pattern 23347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param negSuffix negative suffix pattern 23357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param complexCurrencyParsing whether it is complex currency parsing or not. 23367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type type of currency to parse against, LONG_NAME only or not. 23377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 23387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final boolean subparse( 23397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String text, ParsePosition parsePosition, DigitList digits, 23407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean status[], Currency currency[], String negPrefix, String negSuffix, String posPrefix, 23417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String posSuffix, boolean parseComplexCurrency, int type) { 23427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int position = parsePosition.getIndex(); 23447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int oldStart = parsePosition.getIndex(); 23457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Match padding before prefix 23477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) { 23487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position = skipPadding(text, position); 23497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Match positive and negative prefixes; prefer longest match. 23527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int posMatch = compareAffix(text, position, false, true, posPrefix, parseComplexCurrency, type, currency); 23537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int negMatch = compareAffix(text, position, true, true, negPrefix, parseComplexCurrency, type, currency); 23547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posMatch >= 0 && negMatch >= 0) { 23557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posMatch > negMatch) { 23567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negMatch = -1; 23577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (negMatch > posMatch) { 23587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posMatch = -1; 23597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posMatch >= 0) { 23627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position += posMatch; 23637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (negMatch >= 0) { 23647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position += negMatch; 23657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 23667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(position); 23677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 23687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Match padding after prefix 23717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) { 23727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position = skipPadding(text, position); 23737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 23747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // process digits or Inf, find decimal position 23767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_INFINITE] = false; 23777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text.regionMatches(position, symbols.getInfinity(), 0, 23787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getInfinity().length())) { 23797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position += symbols.getInfinity().length(); 23807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_INFINITE] = true; 23817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 23827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We now have a string of digits, possibly with grouping symbols, and decimal 23837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // points. We want to process these into a DigitList. We don't want to put a 23847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // bunch of leading zeros into the DigitList though, so we keep track of the 23857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // location of the decimal point, put only significant digits into the 23867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DigitList, and adjust the exponent as needed. 23877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.decimalAt = digits.count = 0; 23897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char [] digitSymbols = symbols.getDigitsLocal(); 23907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char decimal = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ? 23917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator(); 23927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char grouping = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ? 23937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getGroupingSeparator() : symbols.getMonetaryGroupingSeparator(); 23947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 23957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String exponentSep = symbols.getExponentSeparator(); 23967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean sawDecimal = false; 23977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean sawGrouping = false; 23987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean sawExponent = false; 23997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean sawDigit = false; 24007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long exponent = 0; // Set to the exponent value, if any 24017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digit = 0; 24027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // strict parsing 24047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean strictParse = isParseStrict(); 24057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean strictFail = false; // did we exit with a strict parse failure? 24067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int lastGroup = -1; // where did we last see a grouping separator? 24077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digitStart = position; // where did the digit start? 24087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2; 24097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY : 24117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getEquivalentDecimals(decimal, strictParse); 24127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UnicodeSet groupEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY : 24137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (strictParse ? strictDefaultGroupingSeparators : defaultGroupingSeparators); 24147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We have to track digitCount ourselves, because digits.count will pin when 24167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the maximum allowable digits is reached. 24177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digitCount = 0; 24187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int backup = -1; 24207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ch; 24217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (; position < text.length(); position += UTF16.getCharCount(ch)) { 24227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = UTF16.charAt(text,position); 24237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We recognize all digit ranges, not only the Latin digit range 24267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // '0'..'9'. We do so by using the UCharacter.digit() method, which 24277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // converts a valid Unicode digit to the range 0..9. 24287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 24297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The character 'ch' may be a digit. If so, place its value from 0 to 9 24307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // in 'digit'. First try using the locale digit, which may or MAY NOT be a 24317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // standard Unicode digit range. If this fails, try using the standard 24327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Unicode digit ranges by calling UCharacter.digit(). If this also fails, 24337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digit will have a value outside the range 0..9. 24347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digit = ch - digitSymbols[0]; 24357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digit < 0 || digit > 9) 24367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digit = UCharacter.digit(ch, 10); 24377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digit < 0 || digit > 9) { 24387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for ( digit = 0 ; digit < 10 ; digit++) { 24397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ( ch == digitSymbols[digit] ) 24407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digit == 0) { 24477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Cancel out backup setting (see grouping handler below) 24487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse && backup != -1) { 24497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // comma followed by digit, so group before comma is a secondary 24507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // group. If there was a group separator before that, the group 24517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // must == the secondary group length, else it can be <= the the 24527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // secondary group length. 24537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2) 24547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) { 24557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 24567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert lastGroup = backup; 24597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert backup = -1; // Do this BEFORE continue statement below!!! 24617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawDigit = true; 24627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle leading zeros 24647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digits.count == 0) { 24657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!sawDecimal) { 24667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ignore leading zeros in integer part of number. 24677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 24687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we have seen the decimal, but no significant digits yet, 24717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // then we account for leading zeros by decrementing the 24727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digits.decimalAt into negative values. 24737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --digits.decimalAt; 24747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 24757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++digitCount; 24767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.append((char) (digit + '0')); 24777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above 24797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 24807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 24817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backup != -1) { 24827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2) 24837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) { 24847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 24857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 24867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert lastGroup = backup; 24887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 24907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawDigit = true; 24927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++digitCount; 24937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.append((char) (digit + '0')); 24947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 24957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Cancel out backup setting (see grouping handler below) 24967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert backup = -1; 24977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == decimal) { 24987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 24997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backup != -1 || 25007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) { 25017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 25027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we're only parsing integers, or if we ALREADY saw the decimal, 25067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // then don't parse this one. 25077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isParseIntegerOnly() || sawDecimal) { 25087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.decimalAt = digitCount; // Not digits.count! 25117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawDecimal = true; 25127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (isGroupingUsed() && ch == grouping) { 25137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (sawDecimal) { 25147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 25177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((!sawDigit || backup != -1)) { 25187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // leading group, or two group separators in a row 25197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 25207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ignore grouping characters, if we are using them, but require that 25247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // they be followed by a digit. Otherwise we backup and reprocess 25257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // them. 25267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert backup = position; 25277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawGrouping = true; 25287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (!sawDecimal && decimalEquiv.contains(ch)) { 25297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 25307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backup != -1 || 25317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) { 25327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 25337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we're only parsing integers, then don't parse this one. 25377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isParseIntegerOnly()) 25387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.decimalAt = digitCount; // Not digits.count! 25407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 25417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Once we see a decimal separator character, we only accept that 25427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // decimal separator character from then on. 25437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimal = (char) ch; 25447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawDecimal = true; 25457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(ch)) { 25467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (sawDecimal) { 25477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 25507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((!sawDigit || backup != -1)) { 25517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // leading group, or two group separators in a row 25527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 25537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Once we see a grouping character, we only accept that grouping 25577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // character from then on. 25587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert grouping = (char) ch; 25597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 25607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ignore grouping characters, if we are using them, but require that 25617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // they be followed by a digit. Otherwise we backup and reprocess 25627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // them. 25637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert backup = position; 25647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawGrouping = true; 25657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (!sawExponent && text.regionMatches(true, position, exponentSep, 0, exponentSep.length())) { 25667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Parse sign, if present 25677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean negExp = false; 25687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int pos = position + exponentSep.length(); 25697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < text.length()) { 25707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = UTF16.charAt(text,pos); 25717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == symbols.getPlusSign()) { 25727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 25737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == symbols.getMinusSign()) { 25747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 25757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negExp = true; 25767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 25797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DigitList exponentDigits = new DigitList(); 25807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponentDigits.count = 0; 25817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < text.length()) { 25827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digit = UTF16.charAt(text,pos) - digitSymbols[0]; 25837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digit < 0 || digit > 9) { 25847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]" 25857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Should update reassign the value of 'ch' in the code: digit 25867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // = Character.digit(ch, 10); [Richard/GCL] 25877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digit = UCharacter.digit(UTF16.charAt(text,pos), 10); 25887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digit >= 0 && digit <= 9) { 25907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponentDigits.append((char) (digit + '0')); 25917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += UTF16.getCharCount(UTF16.charAt(text,pos)); 25927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 25937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 25947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 25967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 25977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (exponentDigits.count > 0) { 25987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // defer strict parse until we know we have a bona-fide exponent 25997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 26007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backup != -1 || lastGroup != -1) { 26017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 26027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 26037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Quick overflow check for exponential part. Actual limit check 26077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // will be done later in this code. 26087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (exponentDigits.count > 10 /* maximum decimal digits for int */) { 26097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negExp) { 26107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // set underflow flag 26117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_UNDERFLOW] = true; 26127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 26137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // set infinite flag 26147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_INFINITE] = true; 26157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 26177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponentDigits.decimalAt = exponentDigits.count; 26187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = exponentDigits.getLong(); 26197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negExp) { 26207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = -exponent; 26217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position = pos; // Advance past the exponent 26247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sawExponent = true; 26257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; // Whether we fail or succeed, we exit this loop 26287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 26297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 26307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(digits.decimalAt == 0 && isDecimalPatternMatchRequired()) { 26347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(this.formatPattern.indexOf(decimal) != -1) { 26357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(oldStart); 26367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(position); 26377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 26387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (backup != -1) 26427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position = backup; 26437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If there was no decimal point we have an integer 26457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!sawDecimal) 26467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.decimalAt = digitCount; // Not digits.count! 26477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check for strict parse errors 26497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse && !sawDecimal) { 26507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1) { 26517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert strictFail = true; 26527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictFail) { 26557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // only set with strictParse and a leading zero error leading zeros are an 26567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // error with strict parsing except immediately before nondigit (except 26577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // group separator followed by digit), or end of text. 26587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(oldStart); 26607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(position); 26617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 26627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Adjust for exponent, if any 26657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent += digits.decimalAt; 26667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (exponent < -getParseMaxDigits()) { 26677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_UNDERFLOW] = true; 26687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (exponent > getParseMaxDigits()) { 26697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_INFINITE] = true; 26707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 26717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digits.decimalAt = (int) exponent; 26727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If none of the text string was recognized. For example, parse "x" with 26757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern "#0.00" (return index and error index both 0) parse "$" with 26767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern "$#0.00". (return index 0 and error index 1). 26777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!sawDigit && digitCount == 0) { 26787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(oldStart); 26797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(oldStart); 26807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 26817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Match padding before suffix 26857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) { 26867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position = skipPadding(text, position); 26877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 26897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Match positive and negative suffixes; prefer longest match. 26907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posMatch >= 0) { 26917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posMatch = compareAffix(text, position, false, false, posSuffix, parseComplexCurrency, type, currency); 26927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negMatch >= 0) { 26947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negMatch = compareAffix(text, position, true, false, negSuffix, parseComplexCurrency, type, currency); 26957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 26967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posMatch >= 0 && negMatch >= 0) { 26977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posMatch > negMatch) { 26987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negMatch = -1; 26997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (negMatch > posMatch) { 27007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posMatch = -1; 27017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fail if neither or both 27057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((posMatch >= 0) == (negMatch >= 0)) { 27067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(position); 27077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 27087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position += (posMatch >= 0 ? posMatch : negMatch); 27117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Match padding after suffix 27137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) { 27147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert position = skipPadding(text, position); 27157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setIndex(position); 27187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert status[STATUS_POSITIVE] = (posMatch >= 0); 27207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parsePosition.getIndex() == oldStart) { 27227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsePosition.setErrorIndex(position); 27237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 27247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 27267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Utility method used to count the number of codepoints 27297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int countCodePoints(String str,int start, int end) { 27307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count = 0; 27317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int index = start; 27327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while ( index < end ) { 27337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert count++; 27347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert index += UTF16.getCharCount(UTF16.charAt(str, index)); 27357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return count; 27377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 27397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns a set of characters equivalent to the given desimal separator used for 27407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * parsing number. This method may return an empty set. 27417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 27427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) { 27437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UnicodeSet equivSet = UnicodeSet.EMPTY; 27447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictParse) { 27457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (strictDotEquivalents.contains(decimal)) { 27467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert equivSet = strictDotEquivalents; 27477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (strictCommaEquivalents.contains(decimal)) { 27487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert equivSet = strictCommaEquivalents; 27497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 27517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (dotEquivalents.contains(decimal)) { 27527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert equivSet = dotEquivalents; 27537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (commaEquivalents.contains(decimal)) { 27547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert equivSet = commaEquivalents; 27557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return equivSet; 27587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 27617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Starting at position, advance past a run of pad characters, if any. Return the 27627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * index of the first character after position that is not a pad character. Result is 27637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * >= position. 27647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 27657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final int skipPadding(String text, int position) { 27667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (position < text.length() && text.charAt(position) == pad) { 27677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++position; 27687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return position; 27707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 27727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 27737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the length matched by the given affix, or -1 if none. Runs of white space 27747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in the affix, match runs of white space in the input. Pattern white space and input 27757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * white space are determined differently; see code. 27767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 27777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text input text 27787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos offset into input at which to begin matching 27797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isNegative 27807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isPrefix 27817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param affixPat affix pattern used for currency affix comparison 27827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param copmplexCurrencyParsing whether it is currency parsing or not 27837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type compare against currency type, LONG_NAME only or not. 27847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param currency return value for parsed currency, for generic currency parsing 27857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * mode, or null for normal parsing. In generic currency parsing mode, any currency 27867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is parsed, not just the currency that this formatter is set to. 27877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return length of input that matches, or -1 if match failure 27887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 27897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int compareAffix(String text, int pos, boolean isNegative, boolean isPrefix, 27907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String affixPat, boolean complexCurrencyParsing, int type, Currency[] currency) { 27917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currency != null || currencyChoice != null || (currencySignCount != CURRENCY_SIGN_COUNT_ZERO && complexCurrencyParsing)) { 27927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return compareComplexAffix(affixPat, text, pos, type, currency); 27937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isPrefix) { 27957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, text, pos); 27967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 27977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, text, pos); 27987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 27997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 28037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Check for bidi marks: LRM, RLM, ALM 28047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 28057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static boolean isBidiMark(int c) { 28067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (c==0x200E || c==0x200F || c==0x061C); 28077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 28107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Remove bidi marks from affix 28117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 28127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static String trimMarksFromAffix(String affix) { 28137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean hasBidiMark = false; 28147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int idx = 0; 28157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (; idx < affix.length(); idx++) { 28167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isBidiMark(affix.charAt(idx))) { 28177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert hasBidiMark = true; 28187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 28197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!hasBidiMark) { 28227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return affix; 28237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder buf = new StringBuilder(); 28267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(affix, 0, idx); 28277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert idx++; // skip the first Bidi mark 28287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (; idx < affix.length(); idx++) { 28297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char c = affix.charAt(idx); 28307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isBidiMark(c)) { 28317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(c); 28327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return buf.toString(); 28367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 28397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Return the length matched by the given affix, or -1 if none. Runs of white space in 28407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the affix, match runs of white space in the input. Pattern white space and input 28417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * white space are determined differently; see code. 28427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 28437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param affix pattern string, taken as a literal 28447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param input input text 28457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos offset into input at which to begin matching 28467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return length of input that matches, or -1 if match failure 28477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 28487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static int compareSimpleAffix(String affix, String input, int pos) { 28497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int start = pos; 28507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Affixes here might consist of sign, currency symbol and related spacing, etc. 28517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For more efficiency we should keep lazily-created trimmed affixes around in 28527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // instance variables instead of trimming each time they are used (the next step). 28537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String trimmedAffix = (affix.length() > 1)? trimMarksFromAffix(affix): affix; 28547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < trimmedAffix.length();) { 28557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int c = UTF16.charAt(trimmedAffix, i); 28567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int len = UTF16.getCharCount(c); 28577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (PatternProps.isWhiteSpace(c)) { 28587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We may have a pattern like: \u200F and input text like: \u200F Note 28597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // that U+200F and U+0020 are Pattern_White_Space but only U+0020 is 28607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // UWhiteSpace. So we have to first do a direct match of the run of RULE 28617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // whitespace in the pattern, then match any extra characters. 28627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean literalMatch = false; 28637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < input.length()) { 28647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ic = UTF16.charAt(input, pos); 28657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ic == c) { 28667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert literalMatch = true; 28677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i += len; 28687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += len; 28697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i == trimmedAffix.length()) { 28707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 28717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = UTF16.charAt(trimmedAffix, i); 28737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert len = UTF16.getCharCount(c); 28747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!PatternProps.isWhiteSpace(c)) { 28757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 28767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (isBidiMark(ic)) { 28787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos++; // just skip over this input text 28797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 28807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 28817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Advance over run in trimmedAffix 28857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = skipPatternWhiteSpace(trimmedAffix, i); 28867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 28877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Advance over run in input text. Must see at least one white space char 28887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // in input, unless we've already matched some characters literally. 28897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int s = pos; 28907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = skipUWhiteSpace(input, pos); 28917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos == s && !literalMatch) { 28927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 28937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 28947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we skip UWhiteSpace in the input text, we need to skip it in the 28957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern. Otherwise, the previous lines may have skipped over text 28967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (such as U+00A0) that is also in the trimmedAffix. 28977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = skipUWhiteSpace(trimmedAffix, i); 28987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 28997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean match = false; 29007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < input.length()) { 29017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ic = UTF16.charAt(input, pos); 29027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!match && equalWithSignCompatibility(ic, c)) { 29037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i += len; 29047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += len; 29057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert match = true; 29067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (isBidiMark(ic)) { 29077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos++; // just skip over this input text 29087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 29097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 29107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!match) { 29137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 29147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos - start; 29187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static boolean equalWithSignCompatibility(int lhs, int rhs) { 29217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return lhs == rhs 29227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (minusSigns.contains(lhs) && minusSigns.contains(rhs)) 29237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (plusSigns.contains(lhs) && plusSigns.contains(rhs)); 29247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 29277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Skips over a run of zero or more Pattern_White_Space characters at pos in text. 29287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 29297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static int skipPatternWhiteSpace(String text, int pos) { 29307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < text.length()) { 29317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int c = UTF16.charAt(text, pos); 29327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!PatternProps.isWhiteSpace(c)) { 29337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 29347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += UTF16.getCharCount(c); 29367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 29387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 29417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Skips over a run of zero or more isUWhiteSpace() characters at pos in text. 29427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 29437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static int skipUWhiteSpace(String text, int pos) { 29447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < text.length()) { 29457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int c = UTF16.charAt(text, pos); 29467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!UCharacter.isUWhiteSpace(c)) { 29477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 29487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += UTF16.getCharCount(c); 29507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 29527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 29557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Skips over a run of zero or more bidi marks at pos in text. 29567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 29577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static int skipBidiMarks(String text, int pos) { 29587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < text.length()) { 29597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int c = UTF16.charAt(text, pos); 29607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!isBidiMark(c)) { 29617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 29627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += UTF16.getCharCount(c); 29647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 29667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 29677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 29687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 29697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the length matched by the given affix, or -1 if none. 29707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 29717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param affixPat pattern string 29727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text input text 29737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos offset into input at which to begin matching 29747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type parse against currency type, LONG_NAME only or not. 29757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param currency return value for parsed currency, for generic 29767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency parsing mode, or null for normal parsing. In generic 29777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency parsing mode, any currency is parsed, not just the 29787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency that this formatter is set to. 29797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return position after the matched text, or -1 if match failure 29807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 29817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int compareComplexAffix(String affixPat, String text, int pos, int type, 29827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency[] currency) { 29837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int start = pos; 29847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < affixPat.length() && pos >= 0;) { 29857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char c = affixPat.charAt(i++); 29867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (c == QUOTE) { 29877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (;;) { 29887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int j = affixPat.indexOf(QUOTE, i); 29897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (j == i) { 29907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = match(text, pos, QUOTE); 29917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = j + 1; 29927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 29937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (j > i) { 29947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = match(text, pos, affixPat.substring(i, j)); 29957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = j + 1; 29967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i < affixPat.length() && affixPat.charAt(i) == QUOTE) { 29977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = match(text, pos, QUOTE); 29987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 29997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // loop again 30007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 30027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Unterminated quote; should be caught by apply 30057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern. 30067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new RuntimeException(); 30077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 30107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 30127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (c) { 30137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case CURRENCY_SIGN: 30147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // since the currency names in choice format is saved the same way as 30157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // other currency names, do not need to do currency choice parsing here. 30167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the general currency parsing parse against all names, including names 30177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // in choice format. assert(currency != null || (getCurrency() != null && 30187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // currencyChoice != null)); 30197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean intl = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN; 30207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (intl) { 30217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 30227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean plural = i < affixPat.length() && affixPat.charAt(i) == CURRENCY_SIGN; 30247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (plural) { 30257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 30267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intl = false; 30277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Parse generic currency -- anything for which we have a display name, or 30297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // any 3-letter ISO code. Try to parse display name for our locale; first 30307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // determine our locale. TODO: use locale in CurrencyPluralInfo 30317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale uloc = getLocale(ULocale.VALID_LOCALE); 30327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (uloc == null) { 30337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // applyPattern has been called; use the symbols 30347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert uloc = symbols.getLocale(ULocale.VALID_LOCALE); 30357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Delegate parse of display name => ISO code to Currency 30377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ParsePosition ppos = new ParsePosition(pos); 30387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // using Currency.parse to handle mixed style parsing. 30397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String iso = Currency.parse(uloc, text, type, ppos); 30407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 30417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If parse succeeds, populate currency[0] 30427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (iso != null) { 30437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currency != null) { 30447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currency[0] = Currency.getInstance(iso); 30457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The formatter is currency-style but the client has not requested 30477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the value of the parsed currency. In this case, if that value does 30487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not match the formatter's current value, then the parse fails. 30497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency effectiveCurr = getEffectiveCurrency(); 30507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (iso.compareTo(effectiveCurr.getCurrencyCode()) != 0) { 30517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = -1; 30527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 30537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = ppos.getIndex(); 30567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 30577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = -1; 30587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 30607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_PERCENT: 30617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = symbols.getPercent(); 30627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 30637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_PER_MILLE: 30647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = symbols.getPerMill(); 30657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 30667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_MINUS: 30677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = symbols.getMinusSign(); 30687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 30697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = match(text, pos, c); 30717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (PatternProps.isWhiteSpace(c)) { 30727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = skipPatternWhiteSpace(affixPat, i); 30737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 30767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos - start; 30777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 30797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 30807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Matches a single character at text[pos] and return the index of the next character 30817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * upon success. Return -1 on failure. If ch is a Pattern_White_Space then match a run of 30827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * white space in text. 30837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 30847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int match(String text, int pos, int ch) { 30857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < 0 || pos >= text.length()) { 30867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 30877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = skipBidiMarks(text, pos); 30897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (PatternProps.isWhiteSpace(ch)) { 30907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Advance over run of white space in input text 30917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Must see at least one white space char in input 30927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int s = pos; 30937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = skipPatternWhiteSpace(text, pos); 30947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos == s) { 30957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 30967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 30987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 30997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos >= text.length() || UTF16.charAt(text, pos) != ch) { 31007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return -1; 31017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = skipBidiMarks(text, pos + UTF16.getCharCount(ch)); 31037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 31047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 31077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Matches a string at text[pos] and return the index of the next character upon 31087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * success. Return -1 on failure. Match a run of white space in str with a run of 31097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * white space in text. 31107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 31117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int match(String text, int pos, String str) { 31127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < str.length() && pos >= 0;) { 31137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int ch = UTF16.charAt(str, i); 31147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i += UTF16.getCharCount(ch); 31157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = match(text, pos, ch); 31167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (PatternProps.isWhiteSpace(ch)) { 31177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = skipPatternWhiteSpace(str, i); 31187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 31217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 31247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns a copy of the decimal format symbols used by this format. 31257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 31267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return desired DecimalFormatSymbols 31277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols 31287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 31297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 31307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public DecimalFormatSymbols getDecimalFormatSymbols() { 31317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 31327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // don't allow multiple references 31337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (DecimalFormatSymbols) symbols.clone(); 31347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (Exception foo) { 31357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; // should never happen 31367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 31407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the decimal format symbols used by this format. The format uses a copy of the 31417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * provided symbols. 31427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 31437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newSymbols desired DecimalFormatSymbols 31447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols 31457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 31467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 31477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { 31487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols = (DecimalFormatSymbols) newSymbols.clone(); 31497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrencyForSymbols(); 31507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixes(null); 31517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 31547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Update the currency object to match the symbols. This method is used only when the 31557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * caller has passed in a symbols object that may not be the default object for its 31567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. 31577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 31587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setCurrencyForSymbols() { 31597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 Update the affix strings according to symbols in order to keep the 31617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // affix strings up to date. [Richard/GCL] 31627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // With the introduction of the Currency object, the currency symbols in the DFS 31647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // object are ignored. For backward compatibility, we check any explicitly set DFS 31657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // object. If it is a default symbols object for its locale, we change the 31667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // currency object to one for that locale. If it is custom, we set the currency to 31677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // null. 31687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DecimalFormatSymbols def = new DecimalFormatSymbols(symbols.getULocale()); 31697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (symbols.getCurrencySymbol().equals(def.getCurrencySymbol()) 31717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && symbols.getInternationalCurrencySymbol() 31727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert .equals(def.getInternationalCurrencySymbol())) { 31737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrency(Currency.getInstance(symbols.getULocale())); 31747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 31757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrency(null); 31767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 31807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the positive prefix. 31817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 31827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: +123, $123, sFr123 31837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the prefix 31847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 31857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 31867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getPositivePrefix() { 31877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return positivePrefix; 31887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 31897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 31907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 31917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the positive prefix. 31927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 31937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: +123, $123, sFr123 31947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue the prefix 31957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 31967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 31977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setPositivePrefix(String newValue) { 31987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert positivePrefix = newValue; 31997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posPrefixPattern = null; 32007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the negative prefix. 32047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: -123, ($123) (with negative suffix), sFr-123 32067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the prefix 32087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getNegativePrefix() { 32117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return negativePrefix; 32127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the negative prefix. 32167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: -123, ($123) (with negative suffix), sFr-123 32187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue the prefix 32197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setNegativePrefix(String newValue) { 32227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negativePrefix = newValue; 32237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPattern = null; 32247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the positive suffix. 32287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example: 123% 32307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the suffix 32327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getPositiveSuffix() { 32357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return positiveSuffix; 32367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the positive suffix. 32407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example: 123% 32427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue the suffix 32437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setPositiveSuffix(String newValue) { 32467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert positiveSuffix = newValue; 32477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posSuffixPattern = null; 32487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the negative suffix. 32527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: -123%, ($123) (with positive suffixes) 32547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the suffix 32567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getNegativeSuffix() { 32597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return negativeSuffix; 32607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the positive suffix. 32647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: 123% 32667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue the suffix 32677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setNegativeSuffix(String newValue) { 32707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negativeSuffix = newValue; 32717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negSuffixPattern = null; 32727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the multiplier for use in percent, permill, etc. For a percentage, set the 32767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent 32777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be 32787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1000. 32797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23 32817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the multiplier 32837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 32857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getMultiplier() { 32867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return multiplier; 32877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 32887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 32897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 32907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the multiplier for use in percent, permill, etc. For a percentage, set the 32917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffixes to have "%" and the multiplier to be 100. (For Arabic, use arabic percent 32927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * symbol). For a permill, set the suffixes to have "\u2031" and the multiplier to be 32937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1000. 32947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Examples: with 100, 1.23 -> "123", and "123" -> 1.23 32967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 32977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue the multiplier 32987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 32997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 33007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMultiplier(int newValue) { 33017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newValue == 0) { 33027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Bad multiplier: " + newValue); 33037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert multiplier = newValue; 33057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 33087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the rounding increment. 33097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 33107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A positive rounding increment, or <code>null</code> if a custom rounding 33117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * increment is not in effect. 33127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingIncrement 33137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingMode 33147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingMode 33157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 33167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 33177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public java.math.BigDecimal getRoundingIncrement() { 33187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingIncrementICU == null) 33197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 33207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return roundingIncrementICU.toBigDecimal(); 33217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 33247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers 33257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be rounded to the number of digits displayed. 33267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 33277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue A positive rounding increment, or <code>null</code> or 33287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal(0.0)</code> to use the default rounding increment. 33297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if <code>newValue</code> is < 0.0 33307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingIncrement 33317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingMode 33327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingMode 33337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 33347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 33357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setRoundingIncrement(java.math.BigDecimal newValue) { 33367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newValue == null) { 33377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingIncrement((BigDecimal) null); 33387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 33397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingIncrement(new BigDecimal(newValue)); 33407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 33447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers 33457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be rounded to the number of digits displayed. 33467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 33477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue A positive rounding increment, or <code>null</code> or 33487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal(0.0)</code> to use the default rounding increment. 33497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if <code>newValue</code> is < 0.0 33507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingIncrement 33517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingMode 33527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingMode 33537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 33547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 33557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setRoundingIncrement(BigDecimal newValue) { 33567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = newValue == null ? 0 : newValue.compareTo(BigDecimal.ZERO); 33577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i < 0) { 33587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal rounding increment"); 33597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i == 0) { 33617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setInternalRoundingIncrement(null); 33627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 33637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setInternalRoundingIncrement(newValue); 33647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetActualRounding(); 33667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 33697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the rounding increment. In the absence of a rounding increment, numbers 33707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will be rounded to the number of digits displayed. 33717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 33727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue A positive rounding increment, or 0.0 to use the default 33737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment. 33747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if <code>newValue</code> is < 0.0 33757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingIncrement 33767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingMode 33777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingMode 33787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 33797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 33807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setRoundingIncrement(double newValue) { 33817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newValue < 0.0) { 33827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal rounding increment"); 33837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newValue == 0.0d) { 33857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setInternalRoundingIncrement((BigDecimal) null); 33867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 33877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Should use BigDecimal#valueOf(double) instead of constructor 33887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to avoid the double precision problem. 33897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setInternalRoundingIncrement(BigDecimal.valueOf(newValue)); 33907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetActualRounding(); 33927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 33937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 33947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 33957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the rounding mode. 33967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 33977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and 33987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal.ROUND_UNNECESSARY</code>. 33997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingIncrement 34007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingIncrement 34017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingMode 34027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.math.BigDecimal 34037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 34067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getRoundingMode() { 34077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return roundingMode; 34087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the rounding mode. This has no effect unless the rounding increment is greater 34127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * than zero. 34137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 34147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and 34157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal.ROUND_UNNECESSARY</code>. 34167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized. 34177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setRoundingIncrement 34187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingIncrement 34197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getRoundingMode 34207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.math.BigDecimal 34217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 34247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setRoundingMode(int roundingMode) { 34257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) { 34267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode); 34277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.roundingMode = roundingMode; 34307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetActualRounding(); 34317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the width to which the output of <code>format()</code> is padded. The width is 34357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * counted in 16-bit code units. 34367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 34377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the format width, or zero if no padding is in effect 34387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setFormatWidth 34397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadCharacter 34407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadCharacter 34417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 34427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 34437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getFormatWidth() { 34467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return formatWidth; 34477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the width to which the output of <code>format()</code> is 34517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padded. The width is counted in 16-bit code units. This method 34527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * also controls whether padding is enabled. 34537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 34547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param width the width to which to pad the result of 34557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>format()</code>, or zero to disable padding 34567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException if <code>width</code> is < 0 34577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getFormatWidth 34587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadCharacter 34597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadCharacter 34607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 34617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 34627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setFormatWidth(int width) { 34657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (width < 0) { 34667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal format width"); 34677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatWidth = width; 34697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the character used to pad to the format width. The default is ' '. 34737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 34747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the pad character 34757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setFormatWidth 34767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getFormatWidth 34777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadCharacter 34787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 34797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 34807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char getPadCharacter() { 34837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pad; 34847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 34857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 34867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 34877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the character used to pad to the format width. If padding is not 34887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * enabled, then this will take effect if padding is later enabled. 34897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 34907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param padChar the pad character 34917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setFormatWidth 34927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getFormatWidth 34937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadCharacter 34947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 34957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 34967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 34977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 34987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setPadCharacter(char padChar) { 34997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pad = padChar; 35007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the position at which padding will take place. This is the location at 35047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which padding will be inserted if the result of <code>format()</code> is shorter 35057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * than the format width. 35067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the pad position, one of <code>PAD_BEFORE_PREFIX</code>, 35087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or 35097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PAD_AFTER_SUFFIX</code>. 35107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setFormatWidth 35117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getFormatWidth 35127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadCharacter 35137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadCharacter 35147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 35157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_PREFIX 35167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_PREFIX 35177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_SUFFIX 35187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_SUFFIX 35197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getPadPosition() { 35227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return padPosition; 35237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the position at which padding will take place. This is the location at 35277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which padding will be inserted if the result of <code>format()</code> is shorter 35287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * than the format width. This has no effect unless padding is enabled. 35297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param padPos the pad position, one of <code>PAD_BEFORE_PREFIX</code>, 35317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PAD_AFTER_PREFIX</code>, <code>PAD_BEFORE_SUFFIX</code>, or 35327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PAD_AFTER_SUFFIX</code>. 35337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException if the pad position in unrecognized 35347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setFormatWidth 35357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getFormatWidth 35367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadCharacter 35377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadCharacter 35387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 35397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_PREFIX 35407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_PREFIX 35417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_SUFFIX 35427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_SUFFIX 35437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setPadPosition(int padPos) { 35467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) { 35477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Illegal pad position"); 35487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPosition = padPos; 35507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns whether or not scientific notation is used. 35547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if this object formats and parses scientific notation 35567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setScientificNotation 35577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMinimumExponentDigits 35587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setMinimumExponentDigits 35597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isExponentSignAlwaysShown 35607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setExponentSignAlwaysShown 35617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isScientificNotation() { 35647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return useExponentialNotation; 35657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets whether or not scientific notation is used. When scientific notation is 35697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * used, the effective maximum number of integer digits is <= 8. If the maximum number 35707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of integer digits is set to more than 8, the effective maximum will be 1. This 35717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * allows this call to generate a 'default' scientific number format without 35727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * additional changes. 35737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param useScientific true if this object formats and parses scientific notation 35757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isScientificNotation 35767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMinimumExponentDigits 35777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setMinimumExponentDigits 35787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isExponentSignAlwaysShown 35797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setExponentSignAlwaysShown 35807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setScientificNotation(boolean useScientific) { 35837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useExponentialNotation = useScientific; 35847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 35857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 35867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 35877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the minimum exponent digits that will be shown. 35887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 35897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the minimum exponent digits that will be shown 35907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setScientificNotation 35917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isScientificNotation 35927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setMinimumExponentDigits 35937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isExponentSignAlwaysShown 35947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setExponentSignAlwaysShown 35957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 35967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 35977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public byte getMinimumExponentDigits() { 35987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return minExponentDigits; 35997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the minimum exponent digits that will be shown. This has no effect 36037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * unless scientific notation is in use. 36047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param minExpDig a value >= 1 indicating the fewest exponent 36067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits that will be shown 36077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @exception IllegalArgumentException if <code>minExpDig</code> < 1 36087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setScientificNotation 36097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isScientificNotation 36107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMinimumExponentDigits 36117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isExponentSignAlwaysShown 36127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setExponentSignAlwaysShown 36137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMinimumExponentDigits(byte minExpDig) { 36167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (minExpDig < 1) { 36177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Exponent digits must be >= 1"); 36187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minExponentDigits = minExpDig; 36207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns whether the exponent sign is always shown. 36247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if the exponent is always prefixed with either the localized minus 36267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sign or the localized plus sign, false if only negative exponents are prefixed with 36277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the localized minus sign. 36287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setScientificNotation 36297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isScientificNotation 36307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setMinimumExponentDigits 36317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMinimumExponentDigits 36327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setExponentSignAlwaysShown 36337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isExponentSignAlwaysShown() { 36367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return exponentSignAlwaysShown; 36377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets whether the exponent sign is always shown. This has no effect unless 36417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * scientific notation is in use. 36427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param expSignAlways true if the exponent is always prefixed with either the 36447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * localized minus sign or the localized plus sign, false if only negative exponents 36457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are prefixed with the localized minus sign. 36467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setScientificNotation 36477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isScientificNotation 36487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setMinimumExponentDigits 36497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMinimumExponentDigits 36507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isExponentSignAlwaysShown 36517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setExponentSignAlwaysShown(boolean expSignAlways) { 36547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponentSignAlwaysShown = expSignAlways; 36557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the grouping size. Grouping size is the number of digits between grouping 36597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separators in the integer portion of a number. For example, in the number 36607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "123,456.78", the grouping size is 3. 36617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setGroupingSize 36637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#isGroupingUsed 36647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols#getGroupingSeparator 36657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getGroupingSize() { 36687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return groupingSize; 36697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the grouping size. Grouping size is the number of digits between grouping 36737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separators in the integer portion of a number. For example, in the number 36747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "123,456.78", the grouping size is 3. 36757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getGroupingSize 36777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#setGroupingUsed 36787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols#setGroupingSeparator 36797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 36817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setGroupingSize(int newValue) { 36827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert groupingSize = (byte) newValue; 36837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 36847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 36857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 36867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the secondary grouping size. In some locales one grouping interval 36877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is used for the least significant integer digits (the primary grouping size), and 36887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * another is used for all others (the secondary grouping size). A formatter 36897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * supporting a secondary grouping size will return a positive integer unequal to the 36907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * primary grouping size returned by <code>getGroupingSize()</code>. For example, if 36917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the primary grouping size is 4, and the secondary grouping size is 2, then the 36927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number 123456789 formats as "1,23,45,6789", and the pattern appears as "#,##,###0". 36937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 36947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the secondary grouping size, or a value less than one if there is none 36957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setSecondaryGroupingSize 36967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#isGroupingUsed 36977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols#getGroupingSeparator 36987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 36997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getSecondaryGroupingSize() { 37017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return groupingSize2; 37027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the secondary grouping size. If set to a value less than 1, then 37067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * secondary grouping is turned off, and the primary grouping size is used for all 37077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * intervals, not just the least significant. 37087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getSecondaryGroupingSize 37107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#setGroupingUsed 37117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols#setGroupingSeparator 37127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 37137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setSecondaryGroupingSize(int newValue) { 37157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert groupingSize2 = (byte) newValue; 37167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the MathContext used by this format. 37207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return desired MathContext 37227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMathContext 37237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 37247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public MathContext getMathContextICU() { 37267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return mathContext; 37277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the MathContext used by this format. 37317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return desired MathContext 37337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMathContext 37347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 37357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public java.math.MathContext getMathContext() { 37377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 37387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // don't allow multiple references 37397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return mathContext == null ? null : new java.math.MathContext(mathContext.getDigits(), 37407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert java.math.RoundingMode.valueOf(mathContext.getRoundingMode())); 37417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (Exception foo) { 37427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; // should never happen 37437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the MathContext used by this format. 37487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue desired MathContext 37507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMathContext 37517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 37527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMathContextICU(MathContext newValue) { 37547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert mathContext = newValue; 37557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the MathContext used by this format. 37597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue desired MathContext 37617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMathContext 37627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 37637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMathContext(java.math.MathContext newValue) { 37657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert mathContext = new MathContext(newValue.getPrecision(), MathContext.SCIENTIFIC, false, 37667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (newValue.getRoundingMode()).ordinal()); 37677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the behavior of the decimal separator with integers. (The decimal 37717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * separator will always appear with decimals.) <p> Example: Decimal ON: 12345 -> 37727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 12345.; OFF: 12345 -> 12345 37737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 37747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 37757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isDecimalSeparatorAlwaysShown() { 37777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return decimalSeparatorAlwaysShown; 37787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When decimal match is not required, the input does not have to 37827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * contain a decimal mark when there is a decimal mark specified in the 37837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern. 37847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param value true if input must contain a match to decimal mark in pattern 37857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Default is false. 37867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 37877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 37887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 37897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setDecimalPatternMatchRequired(boolean value) { 37907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseRequireDecimalPoint = value; 37917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 37927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 37937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 37947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns whether the input to parsing must contain a decimal mark if there 37957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is a decimal mark in the pattern. 37967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if input must contain a match to decimal mark in pattern 37977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 37987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 37997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isDecimalPatternMatchRequired() { 38017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return parseRequireDecimalPoint; 38027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 38067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the behavior of the decimal separator with integers. (The decimal separator 38077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * will always appear with decimals.) 38087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 38097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>This only affects formatting, and only where there might be no digits after the 38107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * decimal point, e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This 38117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is independent of parsing. If you want parsing to stop at the decimal point, use 38127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * setParseIntegerOnly. 38137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 38147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 38157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345 38167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 38177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 38187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setDecimalSeparatorAlwaysShown(boolean newValue) { 38207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalSeparatorAlwaysShown = newValue; 38217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 38247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns a copy of the CurrencyPluralInfo used by this format. It might 38257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * return null if the decimal format is not a plural type currency decimal 38267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format. Plural type currency decimal format means either the pattern in the decimal 38277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * format contains 3 currency signs, or the decimal format is initialized with 38287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * PLURALCURRENCYSTYLE. 38297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 38307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return desired CurrencyPluralInfo 38317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CurrencyPluralInfo 38327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 38337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public CurrencyPluralInfo getCurrencyPluralInfo() { 38357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 38367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // don't allow multiple references 38377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return currencyPluralInfo == null ? null : 38387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (CurrencyPluralInfo) currencyPluralInfo.clone(); 38397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (Exception foo) { 38407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; // should never happen 38417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 38457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the CurrencyPluralInfo used by this format. The format uses a copy of 38467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the provided information. 38477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 38487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newInfo desired CurrencyPluralInfo 38497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CurrencyPluralInfo 38507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 38517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) { 38537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = (CurrencyPluralInfo) newInfo.clone(); 38547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isReadyForParsing = false; 38557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 38587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides clone. 38597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 38607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 38627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object clone() { 38637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 38647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DecimalFormat other = (DecimalFormat) super.clone(); 38657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.symbols = (DecimalFormatSymbols) symbols.clone(); 38667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.digitList = new DigitList(); // fix for JB#5358 38677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencyPluralInfo != null) { 38687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone(); 38697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.attributes = new ArrayList<FieldPosition>(); // #9240 38717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert other.currencyUsage = currencyUsage; 38727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO: We need to figure out whether we share a single copy of DigitList by 38747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // multiple cloned copies. format/subformat are designed to use a single 38757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // instance, but parse/subparse implementation is not. 38767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return other; 38777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (Exception e) { 38787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalStateException(); 38797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 38817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 38837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides equals. 38847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 38857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 38867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 38877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object obj) { 38887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (obj == null) 38897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 38907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!super.equals(obj)) 38917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; // super does class check 38927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 38937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DecimalFormat other = (DecimalFormat) obj; 38947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Add the comparison of the four new added fields ,they are posPrefixPattern, 38957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // posSuffixPattern, negPrefixPattern, negSuffixPattern. [Richard/GCL] 38967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // following are added to accomodate changes for currency plural format. 38977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return currencySignCount == other.currencySignCount 38987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (style != NumberFormat.PLURALCURRENCYSTYLE || 38997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert equals(posPrefixPattern, other.posPrefixPattern) 39007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && equals(posSuffixPattern, other.posSuffixPattern) 39017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && equals(negPrefixPattern, other.negPrefixPattern) 39027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && equals(negSuffixPattern, other.negSuffixPattern)) 39037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && multiplier == other.multiplier 39047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && groupingSize == other.groupingSize 39057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && groupingSize2 == other.groupingSize2 39067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown 39077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && useExponentialNotation == other.useExponentialNotation 39087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (!useExponentialNotation || minExponentDigits == other.minExponentDigits) 39097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && useSignificantDigits == other.useSignificantDigits 39107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (!useSignificantDigits || minSignificantDigits == other.minSignificantDigits 39117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && maxSignificantDigits == other.maxSignificantDigits) 39127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && symbols.equals(other.symbols) 39137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && Utility.objectEquals(currencyPluralInfo, other.currencyPluralInfo) 39147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && currencyUsage.equals(other.currencyUsage); 39157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // method to unquote the strings and compare 39187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean equals(String pat1, String pat2) { 39197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pat1 == null || pat2 == null) { 39207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (pat1 == null && pat2 == null); 39217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fast path 39237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pat1.equals(pat2)) { 39247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 39257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return unquote(pat1).equals(unquote(pat2)); 39277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String unquote(String pat) { 39307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder buf = new StringBuilder(pat.length()); 39317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i = 0; 39327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (i < pat.length()) { 39337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = pat.charAt(i++); 39347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch != QUOTE) { 39357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(ch); 39367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return buf.toString(); 39397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // protected void handleToString(StringBuffer buf) { 39427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("\nposPrefixPattern: '" + posPrefixPattern + "'\n"); 39437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("positivePrefix: '" + positivePrefix + "'\n"); 39447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("posSuffixPattern: '" + posSuffixPattern + "'\n"); 39457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("positiveSuffix: '" + positiveSuffix + "'\n"); 39467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("negPrefixPattern: '" + 39477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // com.ibm.icu.impl.Utility.format1ForSource(negPrefixPattern) + "'\n"); 39487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("negativePrefix: '" + 39497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // com.ibm.icu.impl.Utility.format1ForSource(negativePrefix) + "'\n"); 39507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("negSuffixPattern: '" + negSuffixPattern + "'\n"); 39517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("negativeSuffix: '" + negativeSuffix + "'\n"); 39527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("multiplier: '" + multiplier + "'\n"); 39537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("groupingSize: '" + groupingSize + "'\n"); 39547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("groupingSize2: '" + groupingSize2 + "'\n"); 39557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("decimalSeparatorAlwaysShown: '" + decimalSeparatorAlwaysShown + "'\n"); 39567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("useExponentialNotation: '" + useExponentialNotation + "'\n"); 39577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("minExponentDigits: '" + minExponentDigits + "'\n"); 39587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("useSignificantDigits: '" + useSignificantDigits + "'\n"); 39597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("minSignificantDigits: '" + minSignificantDigits + "'\n"); 39607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("maxSignificantDigits: '" + maxSignificantDigits + "'\n"); 39617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // buf.append("symbols: '" + symbols + "'"); 39627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // } 39637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 39657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Overrides hashCode. 39667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 39677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 39687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 39697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() { 39707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return super.hashCode() * 37 + positivePrefix.hashCode(); 39717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // just enough fields for a reasonable distribution 39727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 39757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Synthesizes a pattern string that represents the current state of this Format 39767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. 39777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 39787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #applyPattern 39797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 39807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 39817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toPattern() { 39827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (style == NumberFormat.PLURALCURRENCYSTYLE) { 39837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the prefix or suffix pattern might not be defined yet, so they can not be 39847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // synthesized, instead, get them directly. but it might not be the actual 39857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern used in formatting. the actual pattern used in formatting depends 39867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // on the formatted number's plural count. 39877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return formatPattern; 39887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return toPattern(false); 39907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 39917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 39927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 39937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Synthesizes a localized pattern string that represents the current state of this 39947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Format object. 39957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 39967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #applyPattern 39977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 39987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 39997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toLocalizedPattern() { 40007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (style == NumberFormat.PLURALCURRENCYSTYLE) { 40017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return formatPattern; 40027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return toPattern(true); 40047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 40077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Expands the affix pattern strings into the expanded affix strings. If any affix 40087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern string is null, do not expand it. This method should be called any time the 40097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * symbols or the affix patterns change in order to keep the expanded affix strings up 40107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to date. This method also will be called before formatting if format currency 40117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plural names, since the plural name is not a static one, it is based on the 40127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency plural count, the affix will be known only after the currency plural count 40137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is know. In which case, the parameter 'pluralCount' will be a non-null currency 40147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plural count. In all other cases, the 'pluralCount' is null, which means it is not 40157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * needed. 40167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 40177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 [Richard/GCL] 40187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void expandAffixes(String pluralCount) { 40197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // expandAffix() will set currencyChoice to a non-null value if 40207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // appropriate AND if it is null. 40217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyChoice = null; 40227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Reuse one StringBuffer for better performance 40247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer buffer = new StringBuffer(); 40257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posPrefixPattern != null) { 40267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffix(posPrefixPattern, pluralCount, buffer, false); 40277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert positivePrefix = buffer.toString(); 40287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (posSuffixPattern != null) { 40307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffix(posSuffixPattern, pluralCount, buffer, false); 40317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert positiveSuffix = buffer.toString(); 40327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negPrefixPattern != null) { 40347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffix(negPrefixPattern, pluralCount, buffer, false); 40357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negativePrefix = buffer.toString(); 40367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negSuffixPattern != null) { 40387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffix(negSuffixPattern, pluralCount, buffer, false); 40397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negativeSuffix = buffer.toString(); 40407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 40437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 40447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Expands an affix pattern into an affix string. All characters in the pattern are 40457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * literal unless bracketed by QUOTEs. The following characters outside QUOTE are 40467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * recognized: PATTERN_PERCENT, PATTERN_PER_MILLE, PATTERN_MINUS, and 40477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * CURRENCY_SIGN. If CURRENCY_SIGN is doubled, it is interpreted as an international 40487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as currency plural 40497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * long names, such as "US Dollars". Any other character outside QUOTE represents 40507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * itself. Quoted text must be well-formed. 40517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method is used in two distinct ways. First, it is used to expand the stored 40537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * affix patterns into actual affixes. For this usage, doFormat must be false. Second, 40547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it is used to expand the stored affix patterns given a specific number (doFormat == 40557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * true), for those rare cases in which a currency format references a ChoiceFormat 40567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (e.g., en_IN display name for INR). The number itself is taken from digitList. 40577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When used in the first way, this method has a side effect: It sets currencyChoice 40597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to a ChoiceFormat object, if the currency's display name in this locale is a 40607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ChoiceFormat pattern (very rare). It only does this if currencyChoice is null to 40617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * start with. 40627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 40637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the non-null, possibly empty pattern 40647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pluralCount the plural count. It is only used for currency plural format. In 40657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which case, it is the plural count of the currency amount. For example, in en_US, 40667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it is the singular "one", or the plural "other". For all other cases, it is null, 40677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and is not being used. 40687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param buffer a scratch StringBuffer; its contents will be lost 40697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param doFormat if false, then the pattern will be expanded, and if a currency 40707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * symbol is encountered that expands to a ChoiceFormat, the currencyChoice member 40717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * variable will be initialized if it is null. If doFormat is true, then it is assumed 40727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * that the currencyChoice has been created, and it will be used to format the value 40737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * in digitList. 40747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 40757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 [Richard/GCL] 40767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void expandAffix(String pattern, String pluralCount, StringBuffer buffer, 40777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean doFormat) { 40787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.setLength(0); 40797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < pattern.length();) { 40807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char c = pattern.charAt(i++); 40817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (c == QUOTE) { 40827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (;;) { 40837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int j = pattern.indexOf(QUOTE, i); 40847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (j == i) { 40857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(QUOTE); 40867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = j + 1; 40877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 40887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (j > i) { 40897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(pattern.substring(i, j)); 40907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = j + 1; 40917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i < pattern.length() && pattern.charAt(i) == QUOTE) { 40927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(QUOTE); 40937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 40947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // loop again 40957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 40967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 40977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 40987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 40997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Unterminated quote; should be caught by apply 41007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern. 41017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new RuntimeException(); 41027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 41057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (c) { 41087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case CURRENCY_SIGN: 41097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // As of ICU 2.2 we use the currency object, and ignore the currency 41107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // symbols in the DFS, unless we have a null currency object. This occurs 41117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if resurrecting a pre-2.2 object or if the user sets a custom DFS. 41127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean intl = i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN; 41137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean plural = false; 41147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (intl) { 41157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 41167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (i < pattern.length() && pattern.charAt(i) == CURRENCY_SIGN) { 41177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plural = true; 41187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert intl = false; 41197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++i; 41207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String s = null; 41237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency currency = getCurrency(); 41247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currency != null) { 41257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // plural name is only needed when pluralCount != null, which means 41267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // when formatting currency plural names. For other cases, 41277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pluralCount == null, and plural names are not needed. 41287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (plural && pluralCount != null) { 41297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isChoiceFormat[] = new boolean[1]; 41307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME, 41317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pluralCount, isChoiceFormat); 41327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (!intl) { 41337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean isChoiceFormat[] = new boolean[1]; 41347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, 41357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert isChoiceFormat); 41367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isChoiceFormat[0]) { 41377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Two modes here: If doFormat is false, we set up 41387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // currencyChoice. If doFormat is true, we use the previously 41397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // created currencyChoice to format the value in digitList. 41407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!doFormat) { 41417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If the currency is handled by a ChoiceFormat, then 41427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we're not going to use the expanded 41437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // patterns. Instantiate the ChoiceFormat and return. 41447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencyChoice == null) { 41457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyChoice = new ChoiceFormat(s); 41467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We could almost return null or "" here, since the 41487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // expanded affixes are almost not used at all in this 41497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // situation. However, one method -- toPattern() -- still 41507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // does use the expanded affixes, in order to set up a 41517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // padding pattern. We use the CURRENCY_SIGN as a 41527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // placeholder. 41537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert s = String.valueOf(CURRENCY_SIGN); 41547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos = new FieldPosition(0); // ignored 41567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyChoice.format(digitList.getDouble(), buffer, pos); 41577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 41587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert s = currency.getCurrencyCode(); 41627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert s = intl ? symbols.getInternationalCurrencySymbol() : 41657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.getCurrencySymbol(); 41667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(s); 41687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 41697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_PERCENT: 41707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = symbols.getPercent(); 41717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 41727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_PER_MILLE: 41737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = symbols.getPerMill(); 41747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 41757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_MINUS: 41767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String minusString = symbols.getMinusString(); 41777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(minusString); 41787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 41797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(c); 41817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 41837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 41847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 41857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Append an affix to the given StringBuffer. 41867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 41877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param buf 41887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * buffer to append to 41897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isNegative 41907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param isPrefix 41917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 41927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix, 41937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean parseAttr) { 41947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencyChoice != null) { 41957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String affixPat = null; 41967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isPrefix) { 41977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPat = isNegative ? negPrefixPattern : posPrefixPattern; 41987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 41997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPat = isNegative ? negSuffixPattern : posSuffixPattern; 42007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer affixBuf = new StringBuffer(); 42027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffix(affixPat, null, affixBuf, true); 42037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(affixBuf); 42047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return affixBuf.length(); 42057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String affix = null; 42087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isPrefix) { 42097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix = isNegative ? negativePrefix : positivePrefix; 42107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 42117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix = isNegative ? negativeSuffix : positiveSuffix; 42127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix 42147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (parseAttr) { 42157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int offset = affix.indexOf(symbols.getCurrencySymbol()); 42167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (-1 == offset) { 42177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offset = affix.indexOf(symbols.getPercent()); 42187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (-1 == offset) { 42197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offset = 0; 42207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length()); 42237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(affix); 42257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return affix.length(); 42267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 42297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [Spark/CDL] This is a newly added method, used to add attributes for prefix and 42307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * suffix. 42317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 42327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void formatAffix2Attribute(String affix, int begin, int end) { 42337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Spark/CDL] It is the invoker's responsibility to ensure that, before the 42347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // invocation of this method, attributes is not null. if( attributes == null ) 42357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // return; 42367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (affix.indexOf(symbols.getCurrencySymbol()) > -1) { 42377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.CURRENCY, begin, end); 42387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (affix.indexOf(symbols.getMinusSign()) > -1) { 42397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.SIGN, begin, end); 42407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (affix.indexOf(symbols.getPercent()) > -1) { 42417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.PERCENT, begin, end); 42427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (affix.indexOf(symbols.getPerMill()) > -1) { 42437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert addAttribute(Field.PERMILLE, begin, end); 42447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 42487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * [Spark/CDL] Use this method to add attribute. 42497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 42507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void addAttribute(Field field, int begin, int end) { 42517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos = new FieldPosition(field); 42527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(begin); 42537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(end); 42547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert attributes.add(pos); 42557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 42587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats the object to an attributed string, and return the corresponding iterator. 42597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 42607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 42617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 42627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 42637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public AttributedCharacterIterator formatToCharacterIterator(Object obj) { 42647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return formatToCharacterIterator(obj, NULL_UNIT); 42657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert AttributedCharacterIterator formatToCharacterIterator(Object obj, Unit unit) { 42687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!(obj instanceof Number)) 42697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 42707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Number number = (Number) obj; 42717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer text = new StringBuffer(); 42727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert unit.writePrefix(text); 42737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert attributes.clear(); 42747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (obj instanceof BigInteger) { 42757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format((BigInteger) number, text, new FieldPosition(0), true); 42767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (obj instanceof java.math.BigDecimal) { 42777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format((java.math.BigDecimal) number, text, new FieldPosition(0) 42787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert , true); 42797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (obj instanceof Double) { 42807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(number.doubleValue(), text, new FieldPosition(0), true); 42817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (obj instanceof Integer || obj instanceof Long) { 42827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert format(number.longValue(), text, new FieldPosition(0), true); 42837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 42847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(); 42857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert unit.writeSuffix(text); 42877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert AttributedString as = new AttributedString(text.toString()); 42887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // add NumberFormat field attributes to the AttributedString 42907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < attributes.size(); i++) { 42917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos = attributes.get(i); 42927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Format.Field attribute = pos.getFieldAttribute(); 42937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex()); 42947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 42967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // return the CharacterIterator from AttributedString 42977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return as.getIterator(); 42987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 42997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 43007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 43017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Appends an affix pattern to the given StringBuffer. Localize unquoted specials. 43027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 43037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix, 43047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean localized) { 43057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String affixPat = null; 43067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isPrefix) { 43077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPat = isNegative ? negPrefixPattern : posPrefixPattern; 43087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 43097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affixPat = isNegative ? negSuffixPattern : posSuffixPattern; 43107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 43127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // When there is a null affix pattern, we use the affix itself. 43137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (affixPat == null) { 43147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String affix = null; 43157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (isPrefix) { 43167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix = isNegative ? negativePrefix : positivePrefix; 43177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 43187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix = isNegative ? negativeSuffix : positiveSuffix; 43197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do this crudely for now: Wrap everything in quotes. 43217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(QUOTE); 43227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < affix.length(); ++i) { 43237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = affix.charAt(i); 43247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == QUOTE) { 43257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(ch); 43267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(ch); 43287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(QUOTE); 43307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return; 43317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 43337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!localized) { 43347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(affixPat); 43357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 43367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i, j; 43377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < affixPat.length(); ++i) { 43387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = affixPat.charAt(i); 43397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (ch) { 43407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case QUOTE: 43417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert j = affixPat.indexOf(QUOTE, i + 1); 43427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (j < 0) { 43437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Malformed affix pattern: " + affixPat); 43447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(affixPat.substring(i, j + 1)); 43467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = j; 43477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 43487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_PER_MILLE: 43497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = symbols.getPerMill(); 43507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 43517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_PERCENT: 43527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = symbols.getPercent(); 43537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 43547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case PATTERN_MINUS: 43557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = symbols.getMinusSign(); 43567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 43577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // check if char is same as any other symbol 43597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == symbols.getDecimalSeparator() || ch == symbols.getGroupingSeparator()) { 43607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(QUOTE); 43617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(ch); 43627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(QUOTE); 43637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 43647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buffer.append(ch); 43657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 43707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 43717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Does the real work of generating a pattern. 43727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 43737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String toPattern(boolean localized) { 43747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuffer result = new StringBuffer(); 43757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT; 43767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char digit = localized ? symbols.getDigit() : PATTERN_DIGIT; 43777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char sigDigit = 0; 43787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useSigDig = areSignificantDigitsUsed(); 43797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig) { 43807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT; 43817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char group = localized ? symbols.getGroupingSeparator() : PATTERN_GROUPING_SEPARATOR; 43837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int i; 43847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int roundingDecimalPos = 0; // Pos of decimal in roundingDigits 43857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String roundingDigits = null; 43867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int padPos = (formatWidth > 0) ? padPosition : -1; 43877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String padSpec = (formatWidth > 0) 43887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ? new StringBuffer(2).append(localized 43897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ? symbols.getPadEscape() 43907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : PATTERN_PAD_ESCAPE).append(pad).toString() 43917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : null; 43927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingIncrementICU != null) { 43937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert i = roundingIncrementICU.scale(); 43947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingDigits = roundingIncrementICU.movePointRight(i).toString(); 43957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingDecimalPos = roundingDigits.length() - i; 43967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 43977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int part = 0; part < 2; ++part) { 43987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // variable not used int partStart = result.length(); 43997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos == PAD_BEFORE_PREFIX) { 44007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(padSpec); 44017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 44037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Use original symbols read from resources in pattern eg. use "\u00A4" 44047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // instead of "$" in Locale.US [Richard/GCL] 44057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendAffixPattern(result, part != 0, true, localized); 44067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos == PAD_AFTER_PREFIX) { 44077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(padSpec); 44087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int sub0Start = result.length(); 44107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0; 44117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) { 44127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert g += groupingSize2; 44137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int maxDig = 0, minDig = 0, maxSigDig = 0; 44157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig) { 44167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minDig = getMinimumSignificantDigits(); 44177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxDig = maxSigDig = getMaximumSignificantDigits(); 44187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 44197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minDig = getMinimumIntegerDigits(); 44207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxDig = getMaximumIntegerDigits(); 44217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useExponentialNotation) { 44237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) { 44247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxDig = 1; 44257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (useSigDig) { 44277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxDig = Math.max(maxDig, g + 1); 44287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 44297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), roundingDecimalPos) + 1; 44307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = maxDig; i > 0; --i) { 44327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useExponentialNotation && i < maxDig && isGroupingPosition(i)) { 44337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(group); 44347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig) { 44367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // #@,@### (maxSigDig == 5, minSigDig == 2) 65 4321 (1-based pos, 44377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // count from the right) Use # if pos > maxSigDig or 1 <= pos <= 44387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (maxSigDig - minSigDig) Use @ if (maxSigDig - minSigDig) < pos <= 44397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // maxSigDig 44407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit); 44417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 44427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingDigits != null) { 44437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int pos = roundingDecimalPos - i; 44447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos >= 0 && pos < roundingDigits.length()) { 44457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append((char) (roundingDigits.charAt(pos) - '0' + zero)); 44467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 44477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(i <= minDig ? zero : digit); 44507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!useSigDig) { 44537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) { 44547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(localized ? symbols.getDecimalSeparator() : 44557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PATTERN_DECIMAL_SEPARATOR); 44567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int pos = roundingDecimalPos; 44587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < getMaximumFractionDigits(); ++i) { 44597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingDigits != null && pos < roundingDigits.length()) { 44607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(pos < 0 ? zero : 44617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (char) (roundingDigits.charAt(pos) - '0' + zero)); 44627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 44637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 44647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(i < getMinimumFractionDigits() ? zero : digit); 44667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useExponentialNotation) { 44697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (localized) { 44707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(symbols.getExponentSeparator()); 44717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 44727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(PATTERN_EXPONENT); 44737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (exponentSignAlwaysShown) { 44757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(localized ? symbols.getPlusSign() : PATTERN_PLUS_SIGN); 44767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (i = 0; i < minExponentDigits; ++i) { 44787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(zero); 44797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padSpec != null && !useExponentialNotation) { 44827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int add = formatWidth 44837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert - result.length() 44847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + sub0Start 44857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert - ((part == 0) 44867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ? positivePrefix.length() + positiveSuffix.length() 44877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : negativePrefix.length() + negativeSuffix.length()); 44887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (add > 0) { 44897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.insert(sub0Start, digit); 44907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++maxDig; 44917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --add; 44927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Only add a grouping separator if we have at least 2 additional 44937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // characters to be added, so we don't end up with ",###". 44947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (add > 1 && isGroupingPosition(maxDig)) { 44957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.insert(sub0Start, group); 44967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert --add; 44977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 44997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos == PAD_BEFORE_SUFFIX) { 45017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(padSpec); 45027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Use original symbols read from resources in pattern eg. use "\u00A4" 45047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // instead of "$" in Locale.US [Richard/GCL] 45057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert appendAffixPattern(result, part != 0, false, localized); 45067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos == PAD_AFTER_SUFFIX) { 45077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(padSpec); 45087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (part == 0) { 45107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (negativeSuffix.equals(positiveSuffix) && 45117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negativePrefix.equals(PATTERN_MINUS + positivePrefix)) { 45127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 45137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 45147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR); 45157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result.toString(); 45197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 45217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 45227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Applies the given pattern to this Format object. A pattern is a short-hand 45237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specification for the various formatting properties. These properties can also be 45247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * changed individually through the various setter methods. 45257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>There is no limit to integer digits are set by this routine, since that is the 45277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * typical end-user desire; use setMaximumInteger if you want to set a real value. For 45287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * negative numbers, use a second pattern, separated by a semicolon 45297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example "#,#00.0#" -> 1,234.56 45317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2 45337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digits. 45347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parentheses. 45367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>In negative patterns, the minimum and maximum counts are ignored; these are 45387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * presumed to be set in the positive pattern. 45397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 45417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 45427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void applyPattern(String pattern) { 45437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern, false); 45447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 45467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 45477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Applies the given pattern to this Format object. The pattern is assumed to be in a 45487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * localized notation. A pattern is a short-hand specification for the various 45497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatting properties. These properties can also be changed individually through 45507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the various setter methods. 45517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>There is no limit to integer digits are set by this routine, since that is the 45537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * typical end-user desire; use setMaximumInteger if you want to set a real value. For 45547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * negative numbers, use a second pattern, separated by a semicolon 45557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example "#,#00.0#" -> 1,234.56 45577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>This means a minimum of 2 integer digits, 1 fraction digit, and a maximum of 2 45597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digits. 45607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses. 45627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>In negative patterns, the minimum and maximum counts are ignored; these are 45647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * presumed to be set in the positive pattern. 45657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 45667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 45677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 45687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void applyLocalizedPattern(String pattern) { 45697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern, true); 45707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 45727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 45737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Does the real work of applying a pattern. 45747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 45757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void applyPattern(String pattern, boolean localized) { 45767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPatternWithoutExpandAffix(pattern, localized); 45777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixAdjustWidth(null); 45787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 45807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void expandAffixAdjustWidth(String pluralCount) { 45817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 Update the affix strings according to symbols in order to keep the 45827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // affix strings up to date. [Richard/GCL] 45837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixes(pluralCount); 45847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 45857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Now that we have the actual prefix and suffix, fix up formatWidth 45867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (formatWidth > 0) { 45877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatWidth += positivePrefix.length() + positiveSuffix.length(); 45887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 45907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 45917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void applyPatternWithoutExpandAffix(String pattern, boolean localized) { 45927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char zeroDigit = PATTERN_ZERO_DIGIT; // '0' 45937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char sigDigit = PATTERN_SIGNIFICANT_DIGIT; // '@' 45947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char groupingSeparator = PATTERN_GROUPING_SEPARATOR; 45957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char decimalSeparator = PATTERN_DECIMAL_SEPARATOR; 45967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char percent = PATTERN_PERCENT; 45977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char perMill = PATTERN_PER_MILLE; 45987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char digit = PATTERN_DIGIT; // '#' 45997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char separator = PATTERN_SEPARATOR; 46007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String exponent = String.valueOf(PATTERN_EXPONENT); 46017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char plus = PATTERN_PLUS_SIGN; 46027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char padEscape = PATTERN_PAD_ESCAPE; 46037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL] 46047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (localized) { 46057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroDigit = symbols.getZeroDigit(); 46067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sigDigit = symbols.getSignificantDigit(); 46077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert groupingSeparator = symbols.getGroupingSeparator(); 46087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalSeparator = symbols.getDecimalSeparator(); 46097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert percent = symbols.getPercent(); 46107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert perMill = symbols.getPerMill(); 46117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digit = symbols.getDigit(); 46127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert separator = symbols.getPatternSeparator(); 46137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponent = symbols.getExponentSeparator(); 46147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plus = symbols.getPlusSign(); 46157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padEscape = symbols.getPadEscape(); 46167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minus = symbols.getMinusSign(); // Bug 4212072 [Richard/GCL] 46177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char nineDigit = (char) (zeroDigit + 9); 46197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 46207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean gotNegative = false; 46217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 46227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int pos = 0; 46237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Part 0 is the positive pattern. Part 1, if present, is the negative 46247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern. 46257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int part = 0; part < 2 && pos < pattern.length(); ++part) { 46267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, 2=suffix, 46277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 3=prefix in quote, 4=suffix in quote. Subpart 0 is between the prefix and 46287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // suffix, and consists of pattern characters. In the prefix and suffix, 46297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // percent, permille, and currency symbols are recognized and translated. 46307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0; 46317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 46327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // It's important that we don't change any fields of this object 46337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // prematurely. We set the following variables for the multiplier, grouping, 46347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // etc., and then only change the actual object fields if everything parses 46357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // correctly. This also lets us register the data from part 0 and ignore the 46367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // part 1, except for the prefix and suffix. 46377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder prefix = new StringBuilder(); 46387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder suffix = new StringBuilder(); 46397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int decimalPos = -1; 46407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int multpl = 1; 46417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0; 46427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert byte groupingCount = -1; 46437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert byte groupingCount2 = -1; 46447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int padPos = -1; 46457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char padChar = 0; 46467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int incrementPos = -1; 46477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert long incrementVal = 0; 46487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert byte expDigits = -1; 46497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean expSignAlways = false; 46507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int currencySignCnt = 0; 46517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 46527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The affix is either the prefix or the suffix. 46537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder affix = prefix; 46547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 46557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int start = pos; 46567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 46577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PARTLOOP: for (; pos < pattern.length(); ++pos) { 46587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char ch = pattern.charAt(pos); 46597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert switch (subpart) { 46607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 0: // Pattern proper subpart (between prefix & suffix) 46617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Process the digits, decimal, and grouping characters. We record 46627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // five pieces of information. We expect the digits to occur in the 46637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern ####00.00####, and we record the number of left digits, 46647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // zero (central) digits, and right digits. The position of the last 46657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // grouping character is recorded (should be somewhere within the 46667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // first two blocks of characters), as is the position of the decimal 46677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // point, if any (should be in the zero digits). If there is no 46687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // decimal point, then there should be no right digits. 46697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == digit) { 46707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (zeroDigitCount > 0 || sigDigitCount > 0) { 46717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++digitRightCount; 46727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 46737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++digitLeftCount; 46747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (groupingCount >= 0 && decimalPos < 0) { 46767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++groupingCount; 46777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if ((ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) { 46797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (digitRightCount > 0) { 46807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Unexpected '" + ch + '\'', pattern); 46817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == sigDigit) { 46837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++sigDigitCount; 46847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 46857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++zeroDigitCount; 46867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch != zeroDigit) { 46877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int p = digitLeftCount + zeroDigitCount + digitRightCount; 46887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (incrementPos >= 0) { 46897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (incrementPos < p) { 46907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert incrementVal *= 10; 46917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++incrementPos; 46927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 46947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert incrementPos = p; 46957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert incrementVal += ch - zeroDigit; 46977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 46997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (groupingCount >= 0 && decimalPos < 0) { 47007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++groupingCount; 47017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == groupingSeparator) { 47037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 process the Localized pattern like 47047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", groupingSeparator 47057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // == QUOTE) [Richard/GCL] 47067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == QUOTE && (pos + 1) < pattern.length()) { 47077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char after = pattern.charAt(pos + 1); 47087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) { 47097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // A quote outside quotes indicates either the opening 47107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // quote or two quotes, which is a quote literal. That is, 47117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we have the first quote in 'do' or o''clock. 47127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (after == QUOTE) { 47137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 47147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fall through to append(ch) 47157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 47167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (groupingCount < 0) { 47177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart = 3; // quoted prefix subpart 47187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 47197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Transition to suffix subpart 47207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart = 2; // suffix subpart 47217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix = suffix; 47227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sub0Limit = pos--; 47237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 47257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 47297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (decimalPos >= 0) { 47307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Grouping separator after decimal", pattern); 47317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert groupingCount2 = groupingCount; 47337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert groupingCount = 0; 47347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == decimalSeparator) { 47357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (decimalPos >= 0) { 47367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Multiple decimal separators", pattern); 47377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Intentionally incorporate the digitRightCount, even though it 47397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // is illegal for this to be > 0 at this point. We check pattern 47407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // syntax below. 47417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; 47427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 47437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pattern.regionMatches(pos, exponent, 0, exponent.length())) { 47447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (expDigits >= 0) { 47457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Multiple exponential symbols", pattern); 47467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (groupingCount >= 0) { 47487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Grouping separator in exponential", pattern); 47497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos += exponent.length(); 47517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check for positive prefix 47527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < pattern.length() && pattern.charAt(pos) == plus) { 47537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expSignAlways = true; 47547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 47557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Use lookahead to parse out the exponential part of the 47577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern, then jump into suffix subpart. 47587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expDigits = 0; 47597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (pos < pattern.length() && pattern.charAt(pos) == zeroDigit) { 47607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++expDigits; 47617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 47627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 47647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 1. Require at least one mantissa pattern digit 47657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 2. Disallow "#+ @" in mantissa 47667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 3. Require at least one exponent pattern digit 47677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (((digitLeftCount + zeroDigitCount) < 1 && 47687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (sigDigitCount + digitRightCount) < 1) 47697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (sigDigitCount > 0 && digitLeftCount > 0) || expDigits < 1) { 47707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Malformed exponential", pattern); 47717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Transition to suffix subpart 47747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart = 2; // suffix subpart 47757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix = suffix; 47767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sub0Limit = pos--; // backup: for() will increment 47777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 47787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 47797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 47807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 1: // Prefix subpart 47817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 2: // Suffix subpart 47827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Process the prefix / suffix characters Process unquoted characters 47837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // seen in prefix or suffix subpart. 47847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 47857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Several syntax characters implicitly begins the next subpart if we 47867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // are in the prefix; otherwise they are illegal if unquoted. 47877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == digit || ch == groupingSeparator || ch == decimalSeparator 47887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (ch >= zeroDigit && ch <= nineDigit) || ch == sigDigit) { 47897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Any of these characters implicitly begins the 47907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // next subpart if we are in the prefix 47917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (subpart == 1) { // prefix subpart 47927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart = 0; // pattern proper subpart 47937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sub0Start = pos--; // Reprocess this character 47947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 47957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == QUOTE) { 47967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 process the Localized pattern like 47977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // "'Fr. '#'##0.05;'Fr.-'#'##0.05" (Locale="CH", 47987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // groupingSeparator == QUOTE) [Richard/GCL] 47997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 48007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // A quote outside quotes indicates either the opening quote 48017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // or two quotes, which is a quote literal. That is, we have 48027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the first quote in 'do' or o''clock. 48037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) { 48047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 48057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); 48067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 48077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart += 2; // open quote 48087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 48107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Unquoted special character '" + ch + '\'', pattern); 48127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == CURRENCY_SIGN) { 48137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Use lookahead to determine if the currency sign is 48147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // doubled or not. 48157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean doubled = (pos + 1) < pattern.length() && 48167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern.charAt(pos + 1) == CURRENCY_SIGN; 48177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 48187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 To meet the need of expandAffix(String, 48197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // StirngBuffer) [Richard/GCL] 48207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (doubled) { 48217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; // Skip over the doubled character 48227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); // append two: one here, one below 48237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((pos + 1) < pattern.length() && 48247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern.charAt(pos + 1) == CURRENCY_SIGN) { 48257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; // Skip over the tripled character 48267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); // append again 48277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencySignCnt = CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT; 48287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 48297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencySignCnt = CURRENCY_SIGN_COUNT_IN_ISO_FORMAT; 48307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 48327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencySignCnt = CURRENCY_SIGN_COUNT_IN_SYMBOL_FORMAT; 48337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fall through to append(ch) 48357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == QUOTE) { 48367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // A quote outside quotes indicates either the opening quote or 48377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // two quotes, which is a quote literal. That is, we have the 48387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // first quote in 'do' or o''clock. 48397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) { 48407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 48417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); // append two: one here, one below 48427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 48437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart += 2; // open quote 48447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fall through to append(ch) 48467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == separator) { 48477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Don't allow separators in the prefix, and don't allow 48487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // separators in the second pattern (part == 1). 48497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (subpart == 1 || part == 1) { 48507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Unquoted special character '" + ch + '\'', pattern); 48517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sub2Limit = pos++; 48537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break PARTLOOP; // Go to next part 48547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == percent || ch == perMill) { 48557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Next handle characters which are appended directly. 48567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (multpl != 1) { 48577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Too many percent/permille characters", pattern); 48587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert multpl = (ch == percent) ? 100 : 1000; 48607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Convert to non-localized pattern 48617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE; 48627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fall through to append(ch) 48637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == minus) { 48647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Convert to non-localized pattern 48657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ch = PATTERN_MINUS; 48667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fall through to append(ch) 48677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (ch == padEscape) { 48687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos >= 0) { 48697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Multiple pad specifiers", pattern); 48707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((pos + 1) == pattern.length()) { 48727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Invalid pad specifier", pattern); 48737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPos = pos++; // Advance past pad char 48757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padChar = pattern.charAt(pos); 48767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 48777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); 48797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 48807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 3: // Prefix subpart, in quote 48817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert case 4: // Suffix subpart, in quote 48827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // A quote within quotes indicates either the closing quote or two 48837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // quotes, which is a quote literal. That is, we have the second quote 48847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // in 'do' or 'don''t'. 48857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ch == QUOTE) { 48867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((pos + 1) < pattern.length() && pattern.charAt(pos + 1) == QUOTE) { 48877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++pos; 48887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); 48897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 48907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert subpart -= 2; // close quote 48917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Fall through to append(ch) 48937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 48947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // NOTE: In ICU 2.2 there was code here to parse quoted percent and 48957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // permille characters _within quotes_ and give them special 48967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // meaning. This is incorrect, since quoted characters are literals 48977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // without special meaning. 48987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert affix.append(ch); 48997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 49007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (subpart == 3 || subpart == 4) { 49047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Unterminated quote", pattern); 49057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (sub0Limit == 0) { 49087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sub0Limit = pattern.length(); 49097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (sub2Limit == 0) { 49127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert sub2Limit = pattern.length(); 49137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle patterns with no '0' pattern character. These patterns are legal, 49167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // but must be recodified to make sense. "##.###" -> "#0.###". ".###" -> 49177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ".0##". 49187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 49197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We allow patterns of the form "####" to produce a zeroDigitCount of zero 49207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (got that?); although this seems like it might make it possible for 49217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // format() to produce empty strings, format() checks for this condition and 49227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // outputs a zero digit in this situation. Having a zeroDigitCount of zero 49237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // yields a minimum integer digits of zero, which allows proper round-trip 49247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // patterns. We don't want "#" to become "#0" when toPattern() is called (even 49257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // though that's what it really is, semantically). 49267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (zeroDigitCount == 0 && sigDigitCount == 0 && 49277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitLeftCount > 0 && decimalPos >= 0) { 49287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Handle "###.###" and "###." and ".###" 49297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int n = decimalPos; 49307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (n == 0) 49317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++n; // Handle ".###" 49327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitRightCount = digitLeftCount - n; 49337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitLeftCount = n - 1; 49347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert zeroDigitCount = 1; 49357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do syntax checking on the digits, decimal points, and quotes. 49387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) 49397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (decimalPos >= 0 49407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && (sigDigitCount > 0 49417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || decimalPos < digitLeftCount 49427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || decimalPos > (digitLeftCount + zeroDigitCount))) 49437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || groupingCount == 0 49447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || groupingCount2 == 0 49457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || (sigDigitCount > 0 && zeroDigitCount > 0) 49467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert || subpart > 2) { // subpart > 2 == unmatched quote 49477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Malformed pattern", pattern); 49487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Make sure pad is at legal position before or after affix. 49517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos >= 0) { 49527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos == start) { 49537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPos = PAD_BEFORE_PREFIX; 49547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (padPos + 2 == sub0Start) { 49557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPos = PAD_AFTER_PREFIX; 49567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (padPos == sub0Limit) { 49577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPos = PAD_BEFORE_SUFFIX; 49587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (padPos + 2 == sub2Limit) { 49597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPos = PAD_AFTER_SUFFIX; 49607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 49617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternError("Illegal pad position", pattern); 49627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (part == 0) { 49667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Set negative affixes temporarily to match the positive 49677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // affixes. Fix this up later after processing both parts. 49687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) 49707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 49717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posPrefixPattern = negPrefixPattern = prefix.toString(); 49727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posSuffixPattern = negSuffixPattern = suffix.toString(); 49737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useExponentialNotation = (expDigits >= 0); 49757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useExponentialNotation) { 49767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minExponentDigits = expDigits; 49777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponentSignAlwaysShown = expSignAlways; 49787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 49797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; 49807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The effectiveDecimalPos is the position the decimal is at or would be 49817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // at if there is no decimal. Note that if decimalPos<0, then 49827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // digitTotalCount == digitLeftCount + zeroDigitCount. 49837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount; 49847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean useSigDig = (sigDigitCount > 0); 49857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setSignificantDigitsUsed(useSigDig); 49867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (useSigDig) { 49877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumSignificantDigits(sigDigitCount); 49887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMaximumSignificantDigits(sigDigitCount + digitRightCount); 49897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 49907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int minInt = effectiveDecimalPos - digitLeftCount; 49917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumIntegerDigits(minInt); 49927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 49937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Upper limit on integer and fraction digits for a Java double 49947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 49957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMaximumIntegerDigits(useExponentialNotation ? digitLeftCount + minInt : 49967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert DOUBLE_INTEGER_DIGITS); 49977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert _setMaximumFractionDigits(decimalPos >= 0 ? 49987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (digitTotalCount - decimalPos) : 0); 49997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumFractionDigits(decimalPos >= 0 ? 50007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (digitLeftCount + zeroDigitCount - decimalPos) : 0); 50017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setGroupingUsed(groupingCount > 0); 50037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.groupingSize = (groupingCount > 0) ? groupingCount : 0; 50047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) 50057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ? groupingCount2 : 0; 50067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.multiplier = multpl; 50077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount); 50087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (padPos >= 0) { 50097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPosition = padPos; 50107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatWidth = sub0Limit - sub0Start; // to be fixed up below 50117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pad = padChar; 50127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 50137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatWidth = 0; 50147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (incrementVal != 0) { 50167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // BigDecimal scale cannot be negative (even though this makes perfect 50177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // sense), so we need to handle this. 50187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int scale = incrementPos - effectiveDecimalPos; 50197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingIncrementICU = BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0); 50207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (scale < 0) { 50217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingIncrementICU = roundingIncrementICU.movePointRight(-scale); 50227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingMode = BigDecimal.ROUND_HALF_EVEN; 50247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 50257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingIncrement((BigDecimal) null); 50267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Update currency sign count for the new pattern 50297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencySignCount = currencySignCnt; 50307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 50317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) 50327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 50337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPattern = prefix.toString(); 50347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negSuffixPattern = suffix.toString(); 50357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert gotNegative = true; 50367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4140009 Process the empty pattern [Richard/GCL] 50417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pattern.length() == 0) { 50427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posPrefixPattern = posSuffixPattern = ""; 50437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumIntegerDigits(0); 50447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS); 50457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumFractionDigits(0); 50467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS); 50477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If there was no negative pattern, or if the negative pattern is identical to 50507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the positive pattern, then prepend the minus sign to the positive pattern to 50517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // form the negative pattern. 50527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL] 50547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!gotNegative || 50567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (negPrefixPattern.equals(posPrefixPattern) 50577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && negSuffixPattern.equals(posSuffixPattern))) { 50587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negSuffixPattern = posSuffixPattern; 50597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPattern = PATTERN_MINUS + posPrefixPattern; 50607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setLocale(null, null); 50627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // save the pattern 50637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatPattern = pattern; 50647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // special handlings for currency instance 50667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) { 50677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // reset rounding increment and max/min fractional digits 50687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // by the currency 50697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency theCurrency = getCurrency(); 50707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (theCurrency != null) { 50717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage)); 50727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int d = theCurrency.getDefaultFractionDigits(currencyUsage); 50737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumFractionDigits(d); 50747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert _setMaximumFractionDigits(d); 50757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // initialize currencyPluralInfo if needed 50787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount == CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT 50797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert && currencyPluralInfo == null) { 50807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyPluralInfo = new CurrencyPluralInfo(symbols.getULocale()); 50817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetActualRounding(); 50847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void patternError(String msg, String pattern) { 50887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException(msg + " in pattern \"" + pattern + '"'); 50897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 50907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Rewrite the following 4 "set" methods Upper limit on integer and fraction digits 50937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // for a Java double [Richard/GCL] 50947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 50957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 50967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the maximum number of digits allowed in the integer portion of a number. This 50977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * override limits the integer digit count to 309. 50987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 50997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#setMaximumIntegerDigits 51007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 51017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 51037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMaximumIntegerDigits(int newValue) { 51047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS)); 51057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the minimum number of digits allowed in the integer portion of a number. This 51097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * override limits the integer digit count to 309. 51107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 51117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#setMinimumIntegerDigits 51127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 51137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 51157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMinimumIntegerDigits(int newValue) { 51167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS)); 51177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the minimum number of significant digits that will be 51217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()} 51227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * returns true. 51237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 51247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the fewest significant digits that will be shown 51257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0 51267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getMinimumSignificantDigits() { 51287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return minSignificantDigits; 51297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns the maximum number of significant digits that will be 51337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * displayed. This value has no effect unless {@link #areSignificantDigitsUsed()} 51347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * returns true. 51357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 51367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the most significant digits that will be shown 51377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0 51387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getMaximumSignificantDigits() { 51407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return maxSignificantDigits; 51417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the minimum number of significant digits that will be displayed. If 51457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>min</code> is less than one then it is set to one. If the maximum significant 51467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits count is less than <code>min</code>, then it is set to <code>min</code>. 51477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This function also enables the use of significant digits by this formatter - 51487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link #areSignificantDigitsUsed()} will return true. 51497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 51507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param min the fewest significant digits to be shown 51517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0 51527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMinimumSignificantDigits(int min) { 51547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (min < 1) { 51557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert min = 1; 51567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pin max sig dig to >= min 51587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int max = Math.max(maxSignificantDigits, min); 51597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minSignificantDigits = min; 51607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxSignificantDigits = max; 51617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setSignificantDigitsUsed(true); 51627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets the maximum number of significant digits that will be displayed. If 51667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>max</code> is less than one then it is set to one. If the minimum significant 51677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits count is greater than <code>max</code>, then it is set to <code>max</code>. 51687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This function also enables the use of significant digits by this formatter - 51697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link #areSignificantDigitsUsed()} will return true. 51707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 51717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param max the most significant digits to be shown 51727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0 51737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMaximumSignificantDigits(int max) { 51757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (max < 1) { 51767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert max = 1; 51777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pin min sig dig to 1..max 51797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int min = Math.min(minSignificantDigits, max); 51807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert minSignificantDigits = min; 51817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert maxSignificantDigits = max; 51827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setSignificantDigitsUsed(true); 51837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Returns true if significant digits are in use or false if integer and 51877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digit counts are in use. 51887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 51897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if significant digits are in use 51907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0 51917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 51927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean areSignificantDigitsUsed() { 51937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return useSignificantDigits; 51947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 51957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 51967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 51977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Sets whether significant digits are in use, or integer and fraction digit 51987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * counts are in use. 51997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 52007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param useSignificantDigits true to use significant digits, or false to use integer 52017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and fraction digit counts 52027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0 52037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 52047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setSignificantDigitsUsed(boolean useSignificantDigits) { 52057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.useSignificantDigits = useSignificantDigits; 52067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 52097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the <tt>Currency</tt> object used to display currency amounts. This takes 52107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * effect immediately, if this format is a currency format. If this format is not a 52117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency format, then the currency object is used if and when this object becomes a 52127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency format through the application of a new pattern. 52137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 52147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param theCurrency new currency object to use. Must not be null. 52157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.2 52167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 52177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 52187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setCurrency(Currency theCurrency) { 52197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If we are a currency format, then modify our affixes to 52207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // encode the currency symbol for the given currency in our 52217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // locale, and adjust the decimal digits and rounding for the 52227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // given currency. 52237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setCurrency(theCurrency); 52257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (theCurrency != null) { 52267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean[] isChoiceFormat = new boolean[1]; 52277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String s = theCurrency.getName(symbols.getULocale(), 52287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency.SYMBOL_NAME, isChoiceFormat); 52297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.setCurrency(theCurrency); 52307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert symbols.setCurrencySymbol(s); 52317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount != CURRENCY_SIGN_COUNT_ZERO) { 52347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (theCurrency != null) { 52357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage)); 52367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int d = theCurrency.getDefaultFractionDigits(currencyUsage); 52377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumFractionDigits(d); 52387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMaximumFractionDigits(d); 52397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currencySignCount != CURRENCY_SIGN_COUNT_IN_PLURAL_FORMAT) { 52417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This is not necessary for plural format type 52427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // because affixes will be resolved in subformat 52437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert expandAffixes(null); 52447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 52497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the <tt>Currency Usage</tt> object used to display currency. 52507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This takes effect immediately, if this format is a 52517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * currency format. 52527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newUsage new currency context object to use. 52537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 52547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 52557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 52567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setCurrencyUsage(CurrencyUsage newUsage) { 52577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newUsage == null) { 52587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new NullPointerException("return value is null at method AAA"); 52597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyUsage = newUsage; 52617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency theCurrency = this.getCurrency(); 52627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We set rounding/digit based on currency context 52647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (theCurrency != null) { 52657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingIncrement(theCurrency.getRoundingIncrement(currencyUsage)); 52667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int d = theCurrency.getDefaultFractionDigits(currencyUsage); 52677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMinimumFractionDigits(d); 52687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert _setMaximumFractionDigits(d); 52697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 52737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the <tt>Currency Usage</tt> object used to display currency 52747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 52757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 52767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 52777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public CurrencyUsage getCurrencyUsage() { 52787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return currencyUsage; 52797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 52827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the currency in effect for this formatter. Subclasses should override this 52837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * method as needed. Unlike getCurrency(), this method should never return null. 52847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 52857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 52867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated This API is ICU internal only. 52877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 52887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 52897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 52907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected Currency getEffectiveCurrency() { 52917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Currency c = getCurrency(); 52927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (c == null) { 52937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert c = Currency.getInstance(symbols.getInternationalCurrencySymbol()); 52947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return c; 52967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 52977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 52987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 52997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the maximum number of digits allowed in the fraction portion of a number. This 53007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * override limits the fraction digit count to 340. 53017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 53027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#setMaximumFractionDigits 53037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 53047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 53067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMaximumFractionDigits(int newValue) { 53077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert _setMaximumFractionDigits(newValue); 53087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetActualRounding(); 53097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 53127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Internal method for DecimalFormat, setting maximum fractional digits 53137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * without triggering actual rounding recalculated. 53147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void _setMaximumFractionDigits(int newValue) { 53167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS)); 53177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 53207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the minimum number of digits allowed in the fraction portion of a number. This 53217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * override limits the fraction digit count to 340. 53227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 53237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#setMinimumFractionDigits 53247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 53257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 53277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setMinimumFractionDigits(int newValue) { 53287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS)); 53297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 53327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets whether {@link #parse(String, ParsePosition)} returns BigDecimal. The 53337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * default value is false. 53347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 53357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param value true if {@link #parse(String, ParsePosition)} 53367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * returns BigDecimal. 53377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 53387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setParseBigDecimal(boolean value) { 53407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parseBigDecimal = value; 53417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 53447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns whether {@link #parse(String, ParsePosition)} returns BigDecimal. 53457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 53467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if {@link #parse(String, ParsePosition)} returns BigDecimal. 53477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.6 53487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean isParseBigDecimal() { 53507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return parseBigDecimal; 53517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 53547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set the maximum number of exponent digits when parsing a number. 53557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the limit is set too high, an OutOfMemoryException may be triggered. 53567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The default value is 1000. 53577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param newValue the new limit 53587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 51 53597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setParseMaxDigits(int newValue) { 53617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (newValue > 0) { 53627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PARSE_MAX_EXPONENT = newValue; 53637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 53677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Get the current maximum number of exponent digits when parsing a 53687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number. 53697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the maximum number of exponent digits for parsing 53707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 51 53717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getParseMaxDigits() { 53737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return PARSE_MAX_EXPONENT; 53747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void writeObject(ObjectOutputStream stream) throws IOException { 53777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ticket#6449 Format.Field instances are not serializable. When 53787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // formatToCharacterIterator is called, attributes (ArrayList) stores 53797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // FieldPosition instances with NumberFormat.Field. Because NumberFormat.Field is 53807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // not serializable, we need to clear the contents of the list when writeObject is 53817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // called. We could remove the field or make it transient, but it will break 53827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // serialization compatibility. 53837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert attributes.clear(); 53847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stream.defaultWriteObject(); 53867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 53877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 53897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * First, read the default serializable fields from the stream. Then if 53907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>serialVersionOnStream</code> is less than 1, indicating that the stream was 53917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * written by JDK 1.1, initialize <code>useExponentialNotation</code> to false, since 53927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it was not present in JDK 1.1. Finally, set serialVersionOnStream back to the 53937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maximum allowed value so that default serialization will work properly if this 53947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object is streamed out again. 53957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 53967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 53977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert stream.defaultReadObject(); 53987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 53997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bug 4185761 validate fields [Richard/GCL] 54007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We only need to check the maximum counts because NumberFormat .readObject has 54027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // already ensured that the maximum is greater than the minimum count. 54037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Commented for compatibility with previous version, and reserved for further use 54057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS || 54067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { throw new 54077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // InvalidObjectException("Digit count out of range"); } 54087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Truncate the maximumIntegerDigits to DOUBLE_INTEGER_DIGITS and 54117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // maximumFractionDigits to DOUBLE_FRACTION_DIGITS 54127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) { 54147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS); 54157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { 54177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert _setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS); 54187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (serialVersionOnStream < 2) { 54207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert exponentSignAlwaysShown = false; 54217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setInternalRoundingIncrement(null); 54227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingMode = BigDecimal.ROUND_HALF_EVEN; 54237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert formatWidth = 0; 54247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pad = ' '; 54257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert padPosition = PAD_BEFORE_PREFIX; 54267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (serialVersionOnStream < 1) { 54277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Didn't have exponential fields 54287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert useExponentialNotation = false; 54297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (serialVersionOnStream < 3) { 54327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Versions prior to 3 do not store a currency object. Create one to match 54337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the DecimalFormatSymbols object. 54347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setCurrencyForSymbols(); 54357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (serialVersionOnStream < 4) { 54377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currencyUsage = CurrencyUsage.STANDARD; 54387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert serialVersionOnStream = currentSerialVersion; 54407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert digitList = new DigitList(); 54417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingIncrement != null) { 54437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setInternalRoundingIncrement(new BigDecimal(roundingIncrement)); 54447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetActualRounding(); 54467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setInternalRoundingIncrement(BigDecimal value) { 54497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingIncrementICU = value; 54507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingIncrement = value == null ? null : value.toBigDecimal(); 54517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 54527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ---------------------------------------------------------------------- 54547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // INSTANCE VARIABLES 54557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ---------------------------------------------------------------------- 54567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient DigitList digitList = new DigitList(); 54587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 54607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The symbol used as a prefix when formatting positive numbers, e.g. "+". 54617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 54627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 54637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPositivePrefix 54647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 54657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String positivePrefix = ""; 54667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 54687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The symbol used as a suffix when formatting positive numbers. This is often an 54697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * empty string. 54707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 54717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 54727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPositiveSuffix 54737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 54747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String positiveSuffix = ""; 54757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 54777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The symbol used as a prefix when formatting negative numbers, e.g. "-". 54787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 54797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 54807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getNegativePrefix 54817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 54827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String negativePrefix = "-"; 54837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 54857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The symbol used as a suffix when formatting negative numbers. This is often an 54867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * empty string. 54877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 54887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 54897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getNegativeSuffix 54907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 54917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String negativeSuffix = ""; 54927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 54937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 54947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The prefix pattern for non-negative numbers. This variable corresponds to 54957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>positivePrefix</code>. 54967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 54977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>This pattern is expanded by the method <code>expandAffix()</code> to 54987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>positivePrefix</code> to update the latter to reflect changes in 54997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>symbols</code>. If this variable is <code>null</code> then 55007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>positivePrefix</code> is taken as a literal value that does not change when 55017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>symbols</code> changes. This variable is always <code>null</code> for 55027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>DecimalFormat</code> objects older than stream version 2 restored from 55037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * stream. 55047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 55087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String posPrefixPattern; 55097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The suffix pattern for non-negative numbers. This variable corresponds to 55127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>positiveSuffix</code>. This variable is analogous to 55137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>posPrefixPattern</code>; see that variable for further documentation. 55147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 55187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String posSuffixPattern; 55197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The prefix pattern for negative numbers. This variable corresponds to 55227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>negativePrefix</code>. This variable is analogous to 55237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>posPrefixPattern</code>; see that variable for further documentation. 55247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 55287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String negPrefixPattern; 55297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The suffix pattern for negative numbers. This variable corresponds to 55327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>negativeSuffix</code>. This variable is analogous to 55337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>posPrefixPattern</code>; see that variable for further documentation. 55347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // [Richard/GCL] 55387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String negSuffixPattern; 55397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formatter for ChoiceFormat-based currency names. If this field is not null, then 55427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * delegate to it to format currency symbols. 55437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since ICU 2.6 55457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private ChoiceFormat currencyChoice; 55477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The multiplier for use in percent, permill, etc. 55507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getMultiplier 55537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int multiplier = 1; 55557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The number of digits between grouping separators in the integer portion of a 55587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number. Must be greater than 0 if <code>NumberFormat.groupingUsed</code> is true. 55597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getGroupingSize 55627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see NumberFormat#isGroupingUsed 55637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private byte groupingSize = 3; // invariant, > 0 if useThousands 55657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The secondary grouping size. This is only used for Hindi numerals, which use a 55687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * primary grouping of 3 and a secondary grouping of 2, e.g., "12,34,567". If this 55697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value is less than 1, then secondary grouping is equal to the primary grouping. 55707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private byte groupingSize2 = 0; 55737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If true, forces the decimal separator to always appear in a formatted number, even 55767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * if the fractional part of the number is zero. 55777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isDecimalSeparatorAlwaysShown 55807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean decimalSeparatorAlwaysShown = false; 55827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The <code>DecimalFormatSymbols</code> object used by this format. It contains the 55857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * symbols used to format numbers, e.g. the grouping separator, decimal separator, and 55867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * so on. 55877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setDecimalFormatSymbols 55907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see DecimalFormatSymbols 55917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 55927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols(); 55937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 55947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 55957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * True to use significant digits rather than integer and fraction digit counts. 55967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 55977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 55987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since ICU 3.0 55997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean useSignificantDigits = false; 56017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The minimum number of significant digits to show. Must be >= 1 and <= 56047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * maxSignificantDigits. Ignored unless useSignificantDigits == true. 56057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since ICU 3.0 56087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int minSignificantDigits = 1; 56107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The maximum number of significant digits to show. Must be >= 56137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * minSignficantDigits. Ignored unless useSignificantDigits == true. 56147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since ICU 3.0 56177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int maxSignificantDigits = 6; 56197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * True to force the use of exponential (i.e. scientific) notation 56227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * when formatting numbers. 56237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *<p> Note that the JDK 1.2 public API provides no way to set this 56257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * field, even though it is supported by the implementation and 56267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the stream format. The intent is that this will be added to the 56277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * API in the future. 56287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean useExponentialNotation; // Newly persistent in JDK 1.2 56327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The minimum number of digits used to display the exponent when a number is 56357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatted in exponential notation. This field is ignored if 56367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>useExponentialNotation</code> is not true. 56377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Note that the JDK 1.2 public API provides no way to set this field, even though 56397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it is supported by the implementation and the stream format. The intent is that 56407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this will be added to the API in the future. 56417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private byte minExponentDigits; // Newly persistent in JDK 1.2 56457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If true, the exponent is always prefixed with either the plus sign or the minus 56487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * sign. Otherwise, only negative exponents are prefixed with the minus sign. This has 56497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * no effect unless <code>useExponentialNotation</code> is true. 56507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 56537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean exponentSignAlwaysShown = false; 56557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The value to which numbers are rounded during formatting. For example, if the 56587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3 56597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a 56607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * positive value if rounding is in effect. Default value <code>null</code>. 56617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 56647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note: this is kept in sync with roundingIncrementICU. 56667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // it is only kept around to avoid a conversion when formatting a java.math.BigDecimal 56677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private java.math.BigDecimal roundingIncrement = null; 56687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The value to which numbers are rounded during formatting. For example, if the 56717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding increment is 0.05, then 13.371 would be formatted as 13.350, assuming 3 56727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * fraction digits. Has the value <code>null</code> if rounding is not in effect, or a 56737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * positive value if rounding is in effect. Default value <code>null</code>. WARNING: 56747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the roundingIncrement value is the one serialized. 56757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 56787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient BigDecimal roundingIncrementICU = null; 56807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The rounding mode. This value controls any rounding operations which occur when 56837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * applying a rounding increment or when reducing the number of fraction digits to 56847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * satisfy a maximum fraction digits limit. The value may assume any of the 56857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal</code> rounding mode values. Default value 56867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>BigDecimal.ROUND_HALF_EVEN</code>. 56877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 56887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 56897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 56907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 56917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int roundingMode = BigDecimal.ROUND_HALF_EVEN; 56927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 56937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 56947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Operations on <code>BigDecimal</code> numbers are controlled by a {@link 56957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * MathContext} object, which provides the context (precision and other information) 56967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the operation. The default <code>MathContext</code> settings are 56977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>digits=0, form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>; 56987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * these settings perform fixed point arithmetic with unlimited precision, as defined 56997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the original BigDecimal class in Java 1.1 and Java 1.2 57007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // context for plain unlimited math 57027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private MathContext mathContext = new MathContext(0, MathContext.PLAIN); 57037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The padded format width, or zero if there is no padding. Must be >= 0. Default 57067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * value zero. 57077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 57097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 57107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int formatWidth = 0; 57127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The character used to pad the result of format to <code>formatWidth</code>, if 57157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padding is in effect. Default value ' '. 57167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 57187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 57197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private char pad = ' '; 57217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The position in the string at which the <code>pad</code> character will be 57247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * inserted, if padding is in effect. Must have a value from 57257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PAD_BEFORE_PREFIX</code> to <code>PAD_AFTER_SUFFIX</code>. Default value 57267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PAD_BEFORE_PREFIX</code>. 57277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 57297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since AlphaWorks NumberFormat 57307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int padPosition = PAD_BEFORE_PREFIX; 57327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * True if {@link #parse(String, ParsePosition)} to return BigDecimal rather than 57357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Long, Double or BigDecimal except special values. This property is introduced for 57367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * J2SE 5 compatibility support. 57377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 57397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since ICU 3.6 57407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setParseBigDecimal(boolean) 57417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #isParseBigDecimal() 57427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private boolean parseBigDecimal = false; 57447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The currency usage for the NumberFormat(standard or cash usage). 57477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * It is used as STANDARD by default 57487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since ICU 54 57497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private CurrencyUsage currencyUsage = CurrencyUsage.STANDARD; 57517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ---------------------------------------------------------------------- 57537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int currentSerialVersion = 4; 57557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The internal serial version which says which version was written Possible values 57587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * are: 57597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 57617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>0</b> (default): versions before JDK 1.2 57637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>1</b>: version from JDK 1.2 and later, which includes the two new fields 57657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>useExponentialNotation</code> and <code>minExponentDigits</code>. 57667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>2</b>: version on AlphaWorks, which adds roundingMode, formatWidth, pad, 57687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * padPosition, exponentSignAlwaysShown, roundingIncrement. 57697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>3</b>: ICU 2.2. Adds currency object. 57717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li><b>4</b>: ICU 54. Adds currency usage(standard vs cash) 57737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 57757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 57777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int serialVersionOnStream = currentSerialVersion; 57797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ---------------------------------------------------------------------- 57817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // CONSTANTS 57827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ---------------------------------------------------------------------- 57837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to 57867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specify pad characters inserted before the prefix. 57877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 57887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 57897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 57907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_PREFIX 57917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_SUFFIX 57927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_SUFFIX 57937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 57947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 57957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int PAD_BEFORE_PREFIX = 0; 57967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 57977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 57987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to 57997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specify pad characters inserted after the prefix. 58007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 58017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 58027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 58037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_PREFIX 58047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_SUFFIX 58057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_SUFFIX 58067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 58077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int PAD_AFTER_PREFIX = 1; 58097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 58117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to 58127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specify pad characters inserted before the suffix. 58137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 58147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 58157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 58167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_PREFIX 58177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_PREFIX 58187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_SUFFIX 58197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 58207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int PAD_BEFORE_SUFFIX = 2; 58227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 58247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to 58257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specify pad characters inserted after the suffix. 58267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 58277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #setPadPosition 58287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #getPadPosition 58297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_PREFIX 58307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_AFTER_PREFIX 58317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see #PAD_BEFORE_SUFFIX 58327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 2.0 58337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static final int PAD_AFTER_SUFFIX = 3; 58357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Constants for characters used in programmatic (unlocalized) patterns. 58377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_ZERO_DIGIT = '0'; 58387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_ONE_DIGIT = '1'; 58397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_TWO_DIGIT = '2'; 58407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_THREE_DIGIT = '3'; 58417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_FOUR_DIGIT = '4'; 58427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_FIVE_DIGIT = '5'; 58437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_SIX_DIGIT = '6'; 58447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_SEVEN_DIGIT = '7'; 58457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_EIGHT_DIGIT = '8'; 58467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_NINE_DIGIT = '9'; 58477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_GROUPING_SEPARATOR = ','; 58487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_DECIMAL_SEPARATOR = '.'; 58497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_DIGIT = '#'; 58507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_SIGNIFICANT_DIGIT = '@'; 58517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_EXPONENT = 'E'; 58527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_PLUS_SIGN = '+'; 58537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Affix 58557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char PATTERN_PER_MILLE = '\u2030'; 58567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char PATTERN_PERCENT = '%'; 58577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final char PATTERN_PAD_ESCAPE = '*'; 58587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 58597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL] 58607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char PATTERN_MINUS = '-'; 58627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Other 58647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char PATTERN_SEPARATOR = ';'; 58657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Pad escape is package private to allow access by DecimalFormatSymbols. 58677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Also plus sign. Also exponent. 58687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 58707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The CURRENCY_SIGN is the standard Unicode symbol for currency. It is used in 58717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * patterns and substitued with either the currency symbol, or if it is doubled, with 58727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the international currency symbol. If the CURRENCY_SIGN is seen in a pattern, then 58737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the decimal separator is replaced with the monetary decimal separator. 58747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 58757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The CURRENCY_SIGN is not localized. 58767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char CURRENCY_SIGN = '\u00A4'; 58787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final char QUOTE = '\''; 58807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 58827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Upper limit on integer and fraction digits for a Java double [Richard/GCL] 58837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int DOUBLE_INTEGER_DIGITS = 309; 58857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int DOUBLE_FRACTION_DIGITS = 340; 58867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 58887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When someone turns on scientific mode, we assume that more than this number of 58897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * digits is due to flipping from some other mode that didn't restrict the maximum, 58907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and so we force 1 integer digit. We don't bother to track and see if someone is 58917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * using exponential notation with more than this number, it wouldn't make sense 58927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * anyway, and this is just to make sure that someone turning on scientific mode with 58937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * default settings doesn't end up with lots of zeroes. 58947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 58957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8; 58967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 58977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Proclaim JDK 1.1 serial compatibility. 58987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = 864413376551465018L; 58997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private ArrayList<FieldPosition> attributes = new ArrayList<FieldPosition>(); 59017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The following are used in currency format 59037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- triple currency sign char array 59057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // private static final char[] tripleCurrencySign = {0xA4, 0xA4, 0xA4}; 59067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- triple currency sign string 59077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // private static final String tripleCurrencyStr = new String(tripleCurrencySign); 59087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 59097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- default currency plural pattern char array 59107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // private static final char[] defaultCurrencyPluralPatternChar = 59117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // {0, '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4}; 59127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- default currency plural pattern string 59137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // private static final String defaultCurrencyPluralPattern = 59147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // new String(defaultCurrencyPluralPatternChar); 59157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // pattern used in this formatter 59177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String formatPattern = ""; 59187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // style is only valid when decimal formatter is constructed by 59197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DecimalFormat(pattern, decimalFormatSymbol, style) 59207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int style = NumberFormat.NUMBERSTYLE; 59217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 59227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Represents whether this is a currency format, and which currency format style. 0: 59237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * not currency format type; 1: currency style -- symbol name, such as "$" for US 59247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * dollar. 2: currency style -- ISO name, such as USD for US dollar. 3: currency style 59257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * -- plural long name, such as "US Dollar" for "1.00 US Dollar", or "US Dollars" for 59267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "3.00 US Dollars". 59277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 59287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int currencySignCount = CURRENCY_SIGN_COUNT_ZERO; 59297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 59317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For parsing purposes, we need to remember all prefix patterns and suffix patterns 59327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * of every currency format pattern, including the pattern of the default currency 59337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * style, ISO currency style, and plural currency style. The patterns are set through 59347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * applyPattern. The following are used to represent the affix patterns in currency 59357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plural formats. 59367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 59377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final class AffixForCurrency { 59387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // negative prefix pattern 59397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String negPrefixPatternForCurrency = null; 59407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // negative suffix pattern 59417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String negSuffixPatternForCurrency = null; 59427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // positive prefix pattern 59437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String posPrefixPatternForCurrency = null; 59447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // positive suffix pattern 59457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String posSuffixPatternForCurrency = null; 59467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final int patternType; 59477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public AffixForCurrency(String negPrefix, String negSuffix, String posPrefix, 59497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String posSuffix, int type) { 59507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negPrefixPatternForCurrency = negPrefix; 59517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert negSuffixPatternForCurrency = negSuffix; 59527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posPrefixPatternForCurrency = posPrefix; 59537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert posSuffixPatternForCurrency = posSuffix; 59547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert patternType = type; 59557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getNegPrefix() { 59587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return negPrefixPatternForCurrency; 59597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getNegSuffix() { 59627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return negSuffixPatternForCurrency; 59637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getPosPrefix() { 59667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return posPrefixPatternForCurrency; 59677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getPosSuffix() { 59707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return posSuffixPatternForCurrency; 59717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getPatternType() { 59747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return patternType; 59757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 59777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Affix pattern set for currency. It is a set of AffixForCurrency, each element of 59797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // the set saves the negative prefix, negative suffix, positive prefix, and positive 59807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // suffix of a pattern. 59817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient Set<AffixForCurrency> affixPatternsForCurrency = null; 59827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // For currency parsing. Since currency parsing needs to parse against all currency 59847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // patterns, before the parsing, we need to set up the affix patterns for all currencies. 59857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient boolean isReadyForParsing = false; 59867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Information needed for DecimalFormat to format/parse currency plural. 59887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private CurrencyPluralInfo currencyPluralInfo = null; 59897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 59907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 59917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Unit is an immutable class for the textual representation of a unit, in 59927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * particular its prefix and suffix. 59937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 59947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author rocketman 59957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 59967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 59977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static class Unit { 59987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final String prefix; 59997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final String suffix; 60007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Unit(String prefix, String suffix) { 60027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.prefix = prefix; 60037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.suffix = suffix; 60047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void writeSuffix(StringBuffer toAppendTo) { 60077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toAppendTo.append(suffix); 60087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void writePrefix(StringBuffer toAppendTo) { 60117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toAppendTo.append(prefix); 60127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 60157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object obj) { 60167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (this == obj) { 60177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 60187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!(obj instanceof Unit)) { 60207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 60217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Unit other = (Unit) obj; 60237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return prefix.equals(other.prefix) && suffix.equals(other.suffix); 60247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 60267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toString() { 60277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return prefix + "/" + suffix; 60287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final Unit NULL_UNIT = new Unit("", ""); 60327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Note about rounding implementation 60347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 60357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The original design intended to skip rounding operation when roundingIncrement is not 60367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // set. However, rounding may need to occur when fractional digits exceed the width of 60377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // fractional part of pattern. 60387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 60397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // DigitList class has built-in rounding mechanism, using ROUND_HALF_EVEN. This implementation 60407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // forces non-null roundingIncrement if the setting is other than ROUND_HALF_EVEN, otherwise, 60417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // when rounding occurs in DigitList by pattern's fractional digits' width, the result 60427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // does not match the rounding mode. 60437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 60447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ideally, all rounding operation should be done in one place like ICU4C trunk does 60457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (ICU4C rounding implementation was rewritten recently). This is intrim implemetation 60467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to fix various issues. In the future, we should entire implementation of rounding 60477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // in this class, like ICU4C did. 60487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // 60497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Once we fully implement rounding logic in DigitList, then following fields and methods 60507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // should be gone. 60517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient BigDecimal actualRoundingIncrementICU = null; 60537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient java.math.BigDecimal actualRoundingIncrement = null; 60547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 60567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The actual rounding increment as a double. 60577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 60587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient double roundingDouble = 0.0; 60597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 60617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If the roundingDouble is the reciprocal of an integer (the most common case!), this 60627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is set to be that integer. Otherwise it is 0.0. 60637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 60647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private transient double roundingDoubleReciprocal = 0.0; 60657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 60677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Set roundingDouble, roundingDoubleReciprocal and actualRoundingIncrement 60687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * based on rounding mode and width of fractional digits. Whenever setting affecting 60697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rounding mode, rounding increment and maximum width of fractional digits, then 60707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * this method must be called. 60717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 60727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * roundingIncrementICU is the field storing the custom rounding increment value, 60737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * while actual rounding increment could be larger. 60747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 60757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void resetActualRounding() { 60767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingIncrementICU != null) { 60777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigDecimal byWidth = getMaximumFractionDigits() > 0 ? 60787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert BigDecimal.ONE.movePointLeft(getMaximumFractionDigits()) : BigDecimal.ONE; 60797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingIncrementICU.compareTo(byWidth) >= 0) { 60807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrementICU = roundingIncrementICU; 60817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 60827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrementICU = byWidth.equals(BigDecimal.ONE) ? null : byWidth; 60837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 60857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingMode == BigDecimal.ROUND_HALF_EVEN || isScientificNotation()) { 60867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This rounding fix is irrelevant if mode is ROUND_HALF_EVEN as DigitList 60877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // does ROUND_HALF_EVEN for us. This rounding fix won't work at all for 60887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // scientific notation. 60897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrementICU = null; 60907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 60917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (getMaximumFractionDigits() > 0) { 60927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrementICU = BigDecimal.ONE.movePointLeft(getMaximumFractionDigits()); 60937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 60947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrementICU = BigDecimal.ONE; 60957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 60987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 60997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (actualRoundingIncrementICU == null) { 61007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingDouble(0.0d); 61017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrement = null; 61027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 61037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert setRoundingDouble(actualRoundingIncrementICU.doubleValue()); 61047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualRoundingIncrement = actualRoundingIncrementICU.toBigDecimal(); 61057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 61067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 61077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 61087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final double roundingIncrementEpsilon = 0.000000001; 61097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 61107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void setRoundingDouble(double newValue) { 61117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingDouble = newValue; 61127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (roundingDouble > 0.0d) { 61137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double rawRoundedReciprocal = 1.0d / roundingDouble; 61147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal); 61157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) { 61167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingDoubleReciprocal = 0.0d; 61177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 61187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 61197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert roundingDoubleReciprocal = 0.0d; 61207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 61217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 61227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 61237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 61247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// eof 6125