1. /*
  2. * @(#)DecimalFormat.java 1.59 01/02/09
  3. *
  4. * Copyright 1996-2001 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. /*
  11. * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  12. * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  13. *
  14. * The original version of this source code and documentation is copyrighted
  15. * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  16. * materials are provided under terms of a License Agreement between Taligent
  17. * and Sun. This technology is protected by multiple US and International
  18. * patents. This notice and attribution to Taligent may not be removed.
  19. * Taligent is a registered trademark of Taligent, Inc.
  20. *
  21. */
  22. package java.text;
  23. import java.util.ResourceBundle;
  24. import java.util.Locale;
  25. import java.io.IOException;
  26. import java.io.InvalidObjectException;
  27. import java.io.ObjectInputStream;
  28. import java.util.Hashtable;
  29. /**
  30. * <code>DecimalFormat</code> is a concrete subclass of
  31. * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
  32. * features designed to make it possible to parse and format numbers in any
  33. * locale, including support for Western, Arabic, and Indic digits. It also
  34. * supports different kinds of numbers, including integers (123), fixed-point
  35. * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
  36. * currency amounts ($123). All of these can be localized.
  37. *
  38. * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
  39. * default locale, call one of <code>NumberFormat</code>'s factory methods, such
  40. * as <code>getInstance()</code>. In general, do not call the
  41. * <code>DecimalFormat</code> constructors directly, since the
  42. * <code>NumberFormat</code> factory methods may return subclasses other than
  43. * <code>DecimalFormat</code>. If you need to customize the format object, do
  44. * something like this:
  45. *
  46. * <blockquote><pre>
  47. * NumberFormat f = NumberFormat.getInstance(loc);
  48. * if (f instanceof DecimalFormat) {
  49. * ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
  50. * }
  51. * </pre></blockquote>
  52. *
  53. * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
  54. * <em>symbols</em>. The pattern may be set directly using
  55. * <code>applyPattern()</code>, or indirectly using the API methods. The
  56. * symbols are stored in a <code>DecimalFormatSymbols</code> object. When using
  57. * the <code>NumberFormat</code> factory methods, the pattern and symbols are
  58. * read from localized <code>ResourceBundle</code>s in the package
  59. * <code>java.text.resource</code>.
  60. *
  61. * <p><strong>Example</strong>
  62. *
  63. * <blockquote><pre>
  64. * <strong>// Print out a number using the localized number, currency,
  65. * // and percent format for each locale</strong>
  66. * Locale[] locales = NumberFormat.getAvailableLocales();
  67. * double myNumber = -1234.56;
  68. * NumberFormat form;
  69. * for (int j=0; j<3; ++j) {
  70. * System.out.println("FORMAT");
  71. * for (int i = 0; i < locales.length; ++i) {
  72. * if (locales[i].getCountry().length() == 0) {
  73. * continue; // Skip language-only locales
  74. * }
  75. * System.out.print(locales[i].getDisplayName());
  76. * switch (j) {
  77. * case 0:
  78. * form = NumberFormat.getInstance(locales[i]); break;
  79. * case 1:
  80. * form = NumberFormat.getCurrencyInstance(locales[i]); break;
  81. * default:
  82. * form = NumberFormat.getPercentInstance(locales[i]); break;
  83. * }
  84. * try {
  85. * // Assume form is a DecimalFormat
  86. * System.out.print(": " + ((DecimalFormat) form).toPattern()
  87. * + " -> " + form.format(myNumber));
  88. * } catch (IllegalArgumentException e) {}
  89. * try {
  90. * System.out.println(" -> " + form.parse(form.format(myNumber)));
  91. * } catch (ParseException e) {}
  92. * }
  93. * }
  94. * </pre></blockquote>
  95. *
  96. * <p><strong>Patterns</strong>
  97. *
  98. * <p>A <code>DecimalFormat</code> pattern contains a postive and negative
  99. * subpattern, for example, "#,##0.00;(#,##0.00)". Each subpattern has a
  100. * prefix, numeric part, and suffix. The negative subpattern is optional; if
  101. * absent, then the positive subpattern prefixed with the localized minus sign
  102. * ('-' in most locales) is used as the negative subpattern. That is, "0.00"
  103. * alone is equivalent to "0.00;-0.00". If there is an explicit negative
  104. * subpattern, it serves only to specify the negative prefix and suffix; the
  105. * number of digits, minimal digits, and other characteristics are all the same
  106. * as the positive pattern. That means that "#,##0.0#;(#)" produces precisely
  107. * the same behavior as "#,##0.0#;(#,##0.0#)".
  108. *
  109. * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
  110. * thousands separators, decimal separators, etc. may be set to arbitrary
  111. * values, and they will appear properly during formatting. However, care must
  112. * be taken that the symbols and strings do not conflict, or parsing will be
  113. * unreliable. For example, either the positive and negative prefixes or the
  114. * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
  115. * to distinguish positive from negative values. (If they are identical, then
  116. * <code>DecimalFormat</code> will behave as if no negative subpattern was
  117. * specified.) Another example is that the decimal separator and thousands
  118. * separator should be distinct characters, or parsing will be impossible.
  119. *
  120. * <p>The grouping separator is commonly used for thousands, but in some
  121. * countries it separates ten-thousands. The grouping size is a constant number
  122. * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
  123. * 1,0000,0000. If you supply a pattern with multiple grouping characters, the
  124. * interval between the last one and the end of the integer is the one that is
  125. * used. So "#,##,###,####" == "######,####" == "##,####,####".
  126. *
  127. * <p>Illegal patterns, such as "#.#.#" or "#.###,###", will cause
  128. * <code>DecimalFormat</code> to throw an <code>IllegalArgumentException</code>
  129. * with a message that describes the problem.
  130. *
  131. * <p><strong>Parsing</strong>
  132. *
  133. * <p><code>DecimalFormat</code> parses all Unicode characters that represent
  134. * decimal digits, as defined by <code>Character.digit()</code>. In addition,
  135. * <code>DecimalFormat</code> also recognizes as digits the ten consecutive
  136. * characters starting with the localized zero digit defined in the
  137. * <code>DecimalFormatSymbols</code> object. During formatting, the
  138. * <code>DecimalFormatSymbols</code>-based digits are output.
  139. *
  140. * <p><code>DecimalFormat.parse</code> returns a subclass of
  141. * <code>java.lang.Number</code> representing the parsed numeric string.
  142. * <code>DecimalFormat</code> chooses the most economical subclass that can
  143. * represent the numeric string. This means most integer values are returned as
  144. * <code>Long</code> objects, no matter how they are written: "17" and "17.000"
  145. * both parse to <code>Long(17)</code>. Values that cannot fit into a
  146. * <code>Long</code> are returned as <code>Double</code>s. This includes values
  147. * with a fractional part, infinite values, <code>NaN</code>, and the value
  148. * -0.0. <code>DecimalFormat</code> does <em>not</em> decide whether to return
  149. * a <code>Double</code> or a <code>Long</code> based on the presence of a
  150. * decimal separator in the source string. Doing so would prevent integers that
  151. * overflow the mantissa of a double, such as "10,000,000,000,000,000.00", from
  152. * being parsed accurately. Currently, the only classes that
  153. * <code>DecimalFormat</code> returns are <code>Long</code> and
  154. * <code>Double</code>, but callers should not rely on this. Callers may use
  155. * the <code>Number</code> methods <code>doubleValue</code>,
  156. * <code>longValue</code>, etc., to obtain the type they want.
  157. *
  158. * <p>If <code>DecimalFormat.parse(String, ParsePosition)</code> fails to parse
  159. * a string, it returns <code>null</code>, leaves the <code>ParsePosition</code>
  160. * index unchanged, and sets the <code>ParsePosition</code> error index. The
  161. * convenience method <code>DecimalFormat.parse(String)</code> indicates parse
  162. * failure by throwing a <code>ParseException</code>.
  163. *
  164. * <p><strong>Special Values</strong>
  165. *
  166. * <p><code>NaN</code> is formatted as a single character, typically
  167. * <code>\uFFFD</code>. This character is determined by the
  168. * <code>DecimalFormatSymbols</code> object. This is the only value for which
  169. * the prefixes and suffixes are not used.
  170. *
  171. * <p>Infinity is formatted as a single character, typically
  172. * <code>\u221E</code>, with the positive or negative prefixes and suffixes
  173. * applied. The infinity character is determined by the
  174. * <code>DecimalFormatSymbols</code> object.
  175. *
  176. * <p>Negative zero ("-0") parses to <code>Double(-0.0)</code>, unless
  177. * <code>isParseIntegerOnly()</code> is true, in which case it parses to
  178. * <code>Long(0)</code>.
  179. *
  180. * <p>
  181. * <strong>Scientific Notation</strong>
  182. *
  183. * <p>Numbers in scientific notation are expressed as the product of a mantissa
  184. * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3. The
  185. * mantissa is often in the range 1.0 <= x < 10.0, but it need not be.
  186. * <code>DecimalFormat</code> can be instructed to format and parse scientific
  187. * notation <em>only via a pattern</em> there is currently no factory method
  188. * that creates a scientific notation format. In a pattern, the exponent
  189. * character immediately followed by one or more digit characters indicates
  190. * scientific notation. Example: "0.###E0" formats the number 1234 as
  191. * "1.234E3".
  192. *
  193. * <ul>
  194. * <li>The number of digit characters after the exponent character gives the
  195. * minimum exponent digit count. There is no maximum. Negative exponents are
  196. * formatted using the localized minus sign, <em>not</em> the prefix and suffix
  197. * from the pattern. This allows patterns such as "0.###E0 m/s".
  198. *
  199. * <li>The minimum and maximum number of integer digits are interpreted
  200. * together:
  201. *
  202. * <ul>
  203. * <li>If the maximum number of integer digits is greater than their minimum number
  204. * and greater than 1, it forces the exponent to be a multiple of the maximum
  205. * number of integer digits, and the minimum number of integer digits to be
  206. * interpreted as 1. The most common use of this is to generate
  207. * <em>engineering notation</em>, in which the exponent is a multiple of three,
  208. * e.g., "##0.#####E0". Using this pattern, the number 12345 formats to
  209. * "12.345E3", and 123456 formats to "123.456E3".
  210. *
  211. * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
  212. * exponent. Example: 0.00123 formatted with "00.###E0" yields "12.3E-4".
  213. * </ul>
  214. *
  215. * <li>The number of significant digits in the mantissa is the sum of the
  216. * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
  217. * unaffected by the maximum integer digits. For example, 12345 formatted with
  218. * "##0.##E0" is "12.3E3". To show all digits, set the significant digits count
  219. * to zero. The number of significant digits does not affect parsing.
  220. *
  221. * <li>Exponential patterns may not contain grouping separators.
  222. * </ul>
  223. *
  224. * <p><strong>Pattern Syntax</strong>
  225. * <pre>
  226. * pattern := pos_pattern{';' neg_pattern}
  227. * pos_pattern := {prefix}number{suffix}
  228. * neg_pattern := {prefix}number{suffix}
  229. * number := integer{'.' fraction}{exponent}
  230. * prefix := '\u0000'..'\uFFFD' - special_characters
  231. * suffix := '\u0000'..'\uFFFD' - special_characters
  232. * integer := min_int | '#' | '#' integer | '#' ',' integer
  233. * min_int := '0' | '0' min_int | '0' ',' min_int
  234. * fraction := '0'* '#'*
  235. * exponent := 'E' '0' '0'*
  236. *
  237. * Notation:
  238. * X* 0 or more instances of X
  239. * { X } 0 or 1 instances of X
  240. * X | Y either X or Y
  241. * X..Y any character from X up to Y, inclusive
  242. * S - T characters in S, except those in T
  243. * </pre>
  244. *
  245. * <p><strong>Special Pattern Characters</strong>
  246. *
  247. * <p>Many characters in a pattern are taken literally; they are matched during
  248. * parsing and output unchanged during formatting. Special characters, on the
  249. * other hand, stand for other characters, strings, or classes of characters.
  250. * They must be quoted, unless noted otherwise, if they are to appear in the
  251. * prefix or suffix as literals.
  252. *
  253. * <p>The characters listed here are used in non-localized patterns. Localized
  254. * patterns use the corresponding characters taken from this formatter's
  255. * <code>DecimalFormatSymbols</code> object instead, and these characters lose
  256. * their special status. Two exceptions are the currency sign and quote, which
  257. * are not localized.
  258. *
  259. * <p><table border=1>
  260. * <tr><th>Symbol<th>Location<th>Localized?<th>Meaning</tr>
  261. * <tr><td>0<td>Number<td>Y<td>Digit
  262. * <tr><td>#<td>Number<td>Y<td>Digit, zero shows as absent</tr>
  263. * <tr><td>.<td>Number<td>Y<td>Decimal separator or monetary decimal separator</tr>
  264. * <tr><td>-<td>Number<td>Y<td>Minus sign</tr>
  265. * <tr><td>,<td>Number<td>Y<td>Grouping separator</tr>
  266. * <tr><td>E<td>Number<td>Y
  267. * <td>Separates mantissa and exponent in scientific notation.
  268. * <em>Need not be quoted in prefix or suffix.</em></tr>
  269. * <tr><td><td>Subpattern boundary<td>Y
  270. * <td>Separates positive and negative subpatterns</tr>
  271. * <tr><td>%<td>Prefix or suffix<td>Y<td>Multiply by 100 and show as percentage</tr>
  272. * <tr><td>\u2030<td>Prefix or suffix<td>Y
  273. * <td>Multiply by 1000 and show as per mille</tr>
  274. * <tr><td>¤<br>(\u00A4)<td>Prefix or suffix<td>N
  275. * <td>Currency sign, replaced by currency symbol. If
  276. * doubled, replaced by international currency symbol.
  277. * If present in a pattern, the monetary decimal separator
  278. * is used instead of the decimal separator.</tr>
  279. * <tr><td>'<td>Prefix or suffix<td>N
  280. * <td>Used to quote special characters in a prefix or suffix,
  281. * for example, <code>"'#'#"</code> formats 123 to
  282. * <code>"#123"</code>. To create a single quote
  283. * itself, use two in a row: <code>"# o''clock"</code>.</tr>
  284. * </table>
  285. * </pre>
  286. *
  287. * @see java.text.Format
  288. * @see java.text.NumberFormat
  289. * @see java.text.ChoiceFormat
  290. * @see java.text.ParsePosition
  291. * @version 1.59 02/09/01
  292. * @author Mark Davis
  293. * @author Alan Liu
  294. */
  295. public class DecimalFormat extends NumberFormat {
  296. /**
  297. * Create a DecimalFormat using the default pattern and symbols
  298. * for the default locale. This is a convenient way to obtain a
  299. * DecimalFormat when internationalization is not the main concern.
  300. * <p>
  301. * To obtain standard formats for a given locale, use the factory methods
  302. * on NumberFormat such as getNumberInstance. These factories will
  303. * return the most appropriate sub-class of NumberFormat for a given
  304. * locale.
  305. * @see java.text.NumberFormat#getInstance
  306. * @see java.text.NumberFormat#getNumberInstance
  307. * @see java.text.NumberFormat#getCurrencyInstance
  308. * @see java.text.NumberFormat#getPercentInstance
  309. */
  310. public DecimalFormat() {
  311. Locale def = Locale.getDefault();
  312. /* try to get the pattern from the cache */
  313. String pattern = (String) cachedLocaleData.get(def);
  314. if (pattern == null) { /* cache miss */
  315. // Get the pattern for the default locale.
  316. ResourceBundle rb = ResourceBundle.getBundle
  317. ("java.text.resources.LocaleElements", def);
  318. String[] all = rb.getStringArray("NumberPatterns");
  319. pattern = all[0];
  320. /* update cache */
  321. cachedLocaleData.put(def, pattern);
  322. }
  323. /* Always applyPattern after the symbols are set */
  324. this.symbols = new DecimalFormatSymbols( def );
  325. applyPattern( pattern, false );
  326. }
  327. /**
  328. * Create a DecimalFormat from the given pattern and the symbols
  329. * for the default locale. This is a convenient way to obtain a
  330. * DecimalFormat when internationalization is not the main concern.
  331. * <p>
  332. * To obtain standard formats for a given locale, use the factory methods
  333. * on NumberFormat such as getNumberInstance. These factories will
  334. * return the most appropriate sub-class of NumberFormat for a given
  335. * locale.
  336. * @param pattern A non-localized pattern string.
  337. * @exception IllegalArgumentException if the given pattern is invalid.
  338. * @see java.text.NumberFormat#getInstance
  339. * @see java.text.NumberFormat#getNumberInstance
  340. * @see java.text.NumberFormat#getCurrencyInstance
  341. * @see java.text.NumberFormat#getPercentInstance
  342. */
  343. public DecimalFormat(String pattern) {
  344. // Always applyPattern after the symbols are set
  345. this.symbols = new DecimalFormatSymbols( Locale.getDefault() );
  346. applyPattern( pattern, false );
  347. }
  348. /**
  349. * Create a DecimalFormat from the given pattern and symbols.
  350. * Use this constructor when you need to completely customize the
  351. * behavior of the format.
  352. * <p>
  353. * To obtain standard formats for a given
  354. * locale, use the factory methods on NumberFormat such as
  355. * getInstance or getCurrencyInstance. If you need only minor adjustments
  356. * to a standard format, you can modify the format returned by
  357. * a NumberFormat factory method.
  358. * @param pattern a non-localized pattern string
  359. * @param symbols the set of symbols to be used
  360. * @exception IllegalArgumentException if the given pattern is invalid
  361. * @see java.text.NumberFormat#getInstance
  362. * @see java.text.NumberFormat#getNumberInstance
  363. * @see java.text.NumberFormat#getCurrencyInstance
  364. * @see java.text.NumberFormat#getPercentInstance
  365. * @see java.text.DecimalFormatSymbols
  366. */
  367. public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
  368. // Always applyPattern after the symbols are set
  369. this.symbols = (DecimalFormatSymbols)symbols.clone();
  370. applyPattern( pattern, false );
  371. }
  372. // Overrides
  373. /**
  374. * Formats a double to produce a string.
  375. * @param number The double to format
  376. * @param toAppendTo where the text is to be appended
  377. * @param fieldPosition On input: an alignment field, if desired.
  378. * On output: the offsets of the alignment field.
  379. * @return The value passed in as the result parameter
  380. * @see java.text.FieldPosition
  381. */
  382. public StringBuffer format(double number, StringBuffer result,
  383. FieldPosition fieldPosition)
  384. {
  385. fieldPosition.setBeginIndex(0);
  386. fieldPosition.setEndIndex(0);
  387. if (Double.isNaN(number))
  388. {
  389. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  390. fieldPosition.setBeginIndex(result.length());
  391. result.append(symbols.getNaN());
  392. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  393. fieldPosition.setEndIndex(result.length());
  394. return result;
  395. }
  396. /* Detecting whether a double is negative is easy with the exception of
  397. * the value -0.0. This is a double which has a zero mantissa (and
  398. * exponent), but a negative sign bit. It is semantically distinct from
  399. * a zero with a positive sign bit, and this distinction is important
  400. * to certain kinds of computations. However, it's a little tricky to
  401. * detect, since (-0.0 == 0.0) and !(-0.0 < 0.0). How then, you may
  402. * ask, does it behave distinctly from +0.0? Well, 1/(-0.0) ==
  403. * -Infinity. Proper detection of -0.0 is needed to deal with the
  404. * issues raised by bugs 4106658, 4106667, and 4147706. Liu 7/6/98.
  405. */
  406. boolean isNegative = (number < 0.0) || (number == 0.0 && 1/number < 0.0);
  407. if (isNegative) number = -number;
  408. // Do this BEFORE checking to see if value is infinite!
  409. if (multiplier != 1) number *= multiplier;
  410. if (Double.isInfinite(number))
  411. {
  412. result.append(isNegative ? negativePrefix : positivePrefix);
  413. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  414. fieldPosition.setBeginIndex(result.length());
  415. result.append(symbols.getInfinity());
  416. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  417. fieldPosition.setEndIndex(result.length());
  418. result.append(isNegative ? negativeSuffix : positiveSuffix);
  419. return result;
  420. }
  421. // At this point we are guaranteed a nonnegative finite
  422. // number.
  423. synchronized(digitList) {
  424. digitList.set(number, useExponentialNotation ?
  425. getMaximumIntegerDigits() + getMaximumFractionDigits() :
  426. getMaximumFractionDigits(),
  427. !useExponentialNotation);
  428. return subformat(result, fieldPosition, isNegative, false);
  429. }
  430. }
  431. /**
  432. * Format a long to produce a string.
  433. * @param number The long to format
  434. * @param toAppendTo where the text is to be appended
  435. * @param fieldPosition On input: an alignment field, if desired.
  436. * On output: the offsets of the alignment field.
  437. * @return The value passed in as the result parameter
  438. * @see java.text.FieldPosition
  439. */
  440. public StringBuffer format(long number, StringBuffer result,
  441. FieldPosition fieldPosition)
  442. {
  443. fieldPosition.setBeginIndex(0);
  444. fieldPosition.setEndIndex(0);
  445. boolean isNegative = (number < 0);
  446. if (isNegative) number = -number;
  447. // In general, long values always represent real finite numbers, so
  448. // we don't have to check for +/- Infinity or NaN. However, there
  449. // is one case we have to be careful of: The multiplier can push
  450. // a number near MIN_VALUE or MAX_VALUE outside the legal range. We
  451. // check for this before multiplying, and if it happens we use doubles
  452. // instead, trading off accuracy for range.
  453. if (multiplier != 1 && multiplier != 0)
  454. {
  455. boolean useDouble = false;
  456. if (number < 0) // This can only happen if number == Long.MIN_VALUE
  457. {
  458. long cutoff = Long.MIN_VALUE / multiplier;
  459. useDouble = (number < cutoff);
  460. }
  461. else
  462. {
  463. long cutoff = Long.MAX_VALUE / multiplier;
  464. useDouble = (number > cutoff);
  465. }
  466. if (useDouble)
  467. {
  468. double dnumber = (double)(isNegative ? -number : number);
  469. return format(dnumber, result, fieldPosition);
  470. }
  471. }
  472. number *= multiplier;
  473. synchronized(digitList) {
  474. digitList.set(number, useExponentialNotation ?
  475. getMaximumIntegerDigits() + getMaximumFractionDigits() : 0);
  476. return subformat(result, fieldPosition, isNegative, true);
  477. }
  478. }
  479. /**
  480. * Complete the formatting of a finite number. On entry, the digitList must
  481. * be filled in with the correct digits.
  482. */
  483. private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition,
  484. boolean isNegative, boolean isInteger)
  485. {
  486. // NOTE: This isn't required anymore because DigitList takes care of this.
  487. //
  488. // // The negative of the exponent represents the number of leading
  489. // // zeros between the decimal and the first non-zero digit, for
  490. // // a value < 0.1 (e.g., for 0.00123, -fExponent == 2). If this
  491. // // is more than the maximum fraction digits, then we have an underflow
  492. // // for the printed representation. We recognize this here and set
  493. // // the DigitList representation to zero in this situation.
  494. //
  495. // if (-digitList.decimalAt >= getMaximumFractionDigits())
  496. // {
  497. // digitList.count = 0;
  498. // }
  499. char zero = symbols.getZeroDigit();
  500. int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
  501. char grouping = symbols.getGroupingSeparator();
  502. char decimal = isCurrencyFormat ?
  503. symbols.getMonetaryDecimalSeparator() :
  504. symbols.getDecimalSeparator();
  505. /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
  506. * format as zero. This allows sensible computations and preserves
  507. * relations such as signum(1/x) = signum(x), where x is +Infinity or
  508. * -Infinity. Prior to this fix, we always formatted zero values as if
  509. * they were positive. Liu 7/6/98.
  510. */
  511. if (digitList.isZero())
  512. {
  513. digitList.decimalAt = 0; // Normalize
  514. }
  515. result.append(isNegative ? negativePrefix : positivePrefix);
  516. if (useExponentialNotation)
  517. {
  518. // Record field information for caller.
  519. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  520. {
  521. fieldPosition.setBeginIndex(result.length());
  522. fieldPosition.setEndIndex(-1);
  523. }
  524. else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD)
  525. {
  526. fieldPosition.setBeginIndex(-1);
  527. }
  528. // Minimum integer digits are handled in exponential format by
  529. // adjusting the exponent. For example, 0.01234 with 3 minimum
  530. // integer digits is "123.4E-4".
  531. // Maximum integer digits are interpreted as indicating the
  532. // repeating range. This is useful for engineering notation, in
  533. // which the exponent is restricted to a multiple of 3. For
  534. // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
  535. // If maximum integer digits are > 1 and are larger than
  536. // minimum integer digits, then minimum integer digits are
  537. // ignored.
  538. int exponent = digitList.decimalAt;
  539. int repeat = getMaximumIntegerDigits();
  540. int minimumIntegerDigits = getMinimumIntegerDigits();
  541. if (repeat > 1 && repeat > minimumIntegerDigits) {
  542. // A repeating range is defined; adjust to it as follows.
  543. // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
  544. // -3,-4,-5=>-6, etc. This takes into account that the
  545. // exponent we have here is off by one from what we expect;
  546. // it is for the format 0.MMMMMx10^n.
  547. if (exponent >= 1) {
  548. exponent = ((exponent - 1) / repeat) * repeat;
  549. } else {
  550. // integer division rounds towards 0
  551. exponent = ((exponent - repeat) / repeat) * repeat;
  552. }
  553. minimumIntegerDigits = 1;
  554. }
  555. else
  556. {
  557. // No repeating range is defined; use minimum integer digits.
  558. exponent -= minimumIntegerDigits;
  559. }
  560. // We now output a minimum number of digits, and more if there
  561. // are more digits, up to the maximum number of digits. We
  562. // place the decimal point after the "integer" digits, which
  563. // are the first (decimalAt - exponent) digits.
  564. int minimumDigits = getMinimumIntegerDigits()
  565. + getMinimumFractionDigits();
  566. // The number of integer digits is handled specially if the number
  567. // is zero, since then there may be no digits.
  568. int integerDigits = digitList.isZero() ? minimumIntegerDigits :
  569. digitList.decimalAt - exponent;
  570. if (minimumDigits < integerDigits) {
  571. minimumDigits = integerDigits;
  572. }
  573. int totalDigits = digitList.count;
  574. if (minimumDigits > totalDigits) totalDigits = minimumDigits;
  575. for (int i=0; i<totalDigits; ++i)
  576. {
  577. if (i == integerDigits)
  578. {
  579. // Record field information for caller.
  580. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  581. fieldPosition.setEndIndex(result.length());
  582. result.append(decimal);
  583. // Record field information for caller.
  584. if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD)
  585. fieldPosition.setBeginIndex(result.length());
  586. }
  587. result.append((i < digitList.count) ?
  588. (char)(digitList.digits[i] + zeroDelta) :
  589. zero);
  590. }
  591. // Record field information
  592. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  593. {
  594. if (fieldPosition.getEndIndex() < 0)
  595. fieldPosition.setEndIndex(result.length());
  596. }
  597. else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD)
  598. {
  599. if (fieldPosition.getBeginIndex() < 0)
  600. fieldPosition.setBeginIndex(result.length());
  601. fieldPosition.setEndIndex(result.length());
  602. }
  603. // The exponent is output using the pattern-specified minimum
  604. // exponent digits. There is no maximum limit to the exponent
  605. // digits, since truncating the exponent would result in an
  606. // unacceptable inaccuracy.
  607. result.append(symbols.getExponentialSymbol());
  608. // For zero values, we force the exponent to zero. We
  609. // must do this here, and not earlier, because the value
  610. // is used to determine integer digit count above.
  611. if (digitList.isZero()) exponent = 0;
  612. boolean negativeExponent = exponent < 0;
  613. if (negativeExponent) exponent = -exponent;
  614. result.append(negativeExponent ? negativePrefix : positivePrefix);
  615. digitList.set(exponent);
  616. for (int i=digitList.decimalAt; i<minExponentDigits; ++i) result.append(zero);
  617. for (int i=0; i<digitList.decimalAt; ++i)
  618. {
  619. result.append((i < digitList.count) ?
  620. (char)(digitList.digits[i] + zeroDelta) : zero);
  621. }
  622. result.append(negativeExponent ? negativeSuffix : positiveSuffix);
  623. }
  624. else
  625. {
  626. // Record field information for caller.
  627. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  628. fieldPosition.setBeginIndex(result.length());
  629. // Output the integer portion. Here 'count' is the total
  630. // number of integer digits we will display, including both
  631. // leading zeros required to satisfy getMinimumIntegerDigits,
  632. // and actual digits present in the number.
  633. int count = getMinimumIntegerDigits();
  634. int digitIndex = 0; // Index into digitList.fDigits[]
  635. if (digitList.decimalAt > 0 && count < digitList.decimalAt)
  636. count = digitList.decimalAt;
  637. // Handle the case where getMaximumIntegerDigits() is smaller
  638. // than the real number of integer digits. If this is so, we
  639. // output the least significant max integer digits. For example,
  640. // the value 1997 printed with 2 max integer digits is just "97".
  641. if (count > getMaximumIntegerDigits())
  642. {
  643. count = getMaximumIntegerDigits();
  644. digitIndex = digitList.decimalAt - count;
  645. }
  646. int sizeBeforeIntegerPart = result.length();
  647. for (int i=count-1; i>=0; --i)
  648. {
  649. if (i < digitList.decimalAt && digitIndex < digitList.count)
  650. {
  651. // Output a real digit
  652. result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
  653. }
  654. else
  655. {
  656. // Output a leading zero
  657. result.append(zero);
  658. }
  659. // Output grouping separator if necessary. Don't output a
  660. // grouping separator if i==0 though; that's at the end of
  661. // the integer part.
  662. if (isGroupingUsed() && i>0 && (groupingSize != 0) && (i % groupingSize == 0))
  663. {
  664. result.append(grouping);
  665. }
  666. }
  667. // Record field information for caller.
  668. if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD)
  669. fieldPosition.setEndIndex(result.length());
  670. // Determine whether or not there are any printable fractional
  671. // digits. If we've used up the digits we know there aren't.
  672. boolean fractionPresent = (getMinimumFractionDigits() > 0) ||
  673. (!isInteger && digitIndex < digitList.count);
  674. // If there is no fraction present, and we haven't printed any
  675. // integer digits, then print a zero. Otherwise we won't print
  676. // _any_ digits, and we won't be able to parse this string.
  677. if (!fractionPresent && result.length() == sizeBeforeIntegerPart)
  678. result.append(zero);
  679. // Output the decimal separator if we always do so.
  680. if (decimalSeparatorAlwaysShown || fractionPresent)
  681. result.append(decimal);
  682. // Record field information for caller.
  683. if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD)
  684. fieldPosition.setBeginIndex(result.length());
  685. for (int i=0; i < getMaximumFractionDigits(); ++i)
  686. {
  687. // Here is where we escape from the loop. We escape if we've output
  688. // the maximum fraction digits (specified in the for expression above).
  689. // We also stop when we've output the minimum digits and either:
  690. // we have an integer, so there is no fractional stuff to display,
  691. // or we're out of significant digits.
  692. if (i >= getMinimumFractionDigits() &&
  693. (isInteger || digitIndex >= digitList.count))
  694. break;
  695. // Output leading fractional zeros. These are zeros that come after
  696. // the decimal but before any significant digits. These are only
  697. // output if abs(number being formatted) < 1.0.
  698. if (-1-i > (digitList.decimalAt-1))
  699. {
  700. result.append(zero);
  701. continue;
  702. }
  703. // Output a digit, if we have any precision left, or a
  704. // zero if we don't. We don't want to output noise digits.
  705. if (!isInteger && digitIndex < digitList.count)
  706. {
  707. result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
  708. }
  709. else
  710. {
  711. result.append(zero);
  712. }
  713. }
  714. // Record field information for caller.
  715. if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD)
  716. fieldPosition.setEndIndex(result.length());
  717. }
  718. result.append(isNegative ? negativeSuffix : positiveSuffix);
  719. return result;
  720. }
  721. /**
  722. * Returns an instance of <code>Number</code> with a value matching the
  723. * given string. The most economical subclass that can represent all the
  724. * bits of the source string is chosen.
  725. * @param text the string to be parsed
  726. * @param parsePosition on entry, where to begin parsing; on exit, just past
  727. * the last parsed character. If parsing fails, the index will not move and
  728. * the error index will be set.
  729. * @return the parsed value, or <code>null</code> if the parse fails
  730. */
  731. public Number parse(String text, ParsePosition parsePosition)
  732. {
  733. // special case NaN
  734. if (text.regionMatches(parsePosition.index, symbols.getNaN(),
  735. 0, symbols.getNaN().length())) {
  736. parsePosition.index = parsePosition.index + symbols.getNaN().length();
  737. return new Double(Double.NaN);
  738. }
  739. boolean[] status = new boolean[STATUS_LENGTH];
  740. if (!subparse(text, parsePosition, digitList, false, status))
  741. return null;
  742. double doubleResult = 0.0;
  743. long longResult = 0;
  744. boolean gotDouble = true;
  745. // Finally, have DigitList parse the digits into a value.
  746. if (status[STATUS_INFINITE])
  747. {
  748. doubleResult = Double.POSITIVE_INFINITY;
  749. }
  750. else if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly()))
  751. {
  752. gotDouble = false;
  753. longResult = digitList.getLong();
  754. }
  755. else doubleResult = digitList.getDouble();
  756. // Divide by multiplier. We have to be careful here not to do unneeded
  757. // conversions between double and long.
  758. if (multiplier != 1)
  759. {
  760. if (gotDouble)
  761. doubleResult /= multiplier;
  762. else {
  763. // Avoid converting to double if we can
  764. if (longResult % multiplier == 0) {
  765. longResult /= multiplier;
  766. } else {
  767. doubleResult = ((double)longResult) / multiplier;
  768. if (doubleResult < 0) doubleResult = -doubleResult;
  769. gotDouble = true;
  770. }
  771. }
  772. }
  773. if (!status[STATUS_POSITIVE])
  774. {
  775. doubleResult = -doubleResult;
  776. // If longResult was Long.MIN_VALUE or a divisor of it (if
  777. // multiplier != 1) then don't negate it.
  778. if (longResult > 0) {
  779. longResult = -longResult;
  780. }
  781. }
  782. // At this point, if we divided the result by the multiplier, the result may
  783. // fit into a long. We check for this case and return a long if possible.
  784. // We must do this AFTER applying the negative (if appropriate) in order to
  785. // handle the case of LONG_MIN; otherwise, if we do this with a positive value
  786. // -LONG_MIN, the double is > 0, but the long is < 0. This is a C++-specific
  787. // situation. We also must retain a double in the case of -0.0, which will
  788. // compare as == to a long 0 cast to a double (bug 4162852).
  789. if (multiplier != 1 && gotDouble)
  790. {
  791. longResult = (long)doubleResult;
  792. gotDouble = (doubleResult != (double)longResult)
  793. || (doubleResult == 0.0 && !status[STATUS_POSITIVE] && !isParseIntegerOnly());
  794. }
  795. return gotDouble ? (Number)new Double(doubleResult) : (Number)new Long(longResult);
  796. }
  797. private static final int STATUS_INFINITE = 0;
  798. private static final int STATUS_POSITIVE = 1;
  799. private static final int STATUS_LENGTH = 2;
  800. /**
  801. * Parse the given text into a number. The text is parsed beginning at
  802. * parsePosition, until an unparseable character is seen.
  803. * @param text The string to parse.
  804. * @param parsePosition The position at which to being parsing. Upon
  805. * return, the first unparseable character.
  806. * @param digits The DigitList to set to the parsed value.
  807. * @param isExponent If true, parse an exponent. This means no
  808. * infinite values and integer only.
  809. * @param status Upon return contains boolean status flags indicating
  810. * whether the value was infinite and whether it was positive.
  811. */
  812. private final boolean subparse(String text, ParsePosition parsePosition,
  813. DigitList digits, boolean isExponent,
  814. boolean status[])
  815. {
  816. int position = parsePosition.index;
  817. int oldStart = parsePosition.index;
  818. int backup;
  819. // check for positivePrefix; take longest
  820. boolean gotPositive = text.regionMatches(position,positivePrefix,0,
  821. positivePrefix.length());
  822. boolean gotNegative = text.regionMatches(position,negativePrefix,0,
  823. negativePrefix.length());
  824. if (gotPositive && gotNegative) {
  825. if (positivePrefix.length() > negativePrefix.length())
  826. gotNegative = false;
  827. else if (positivePrefix.length() < negativePrefix.length())
  828. gotPositive = false;
  829. }
  830. if (gotPositive) {
  831. position += positivePrefix.length();
  832. } else if (gotNegative) {
  833. position += negativePrefix.length();
  834. } else {
  835. parsePosition.errorIndex = position;
  836. return false;
  837. }
  838. // process digits or Inf, find decimal position
  839. status[STATUS_INFINITE] = false;
  840. if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0,
  841. symbols.getInfinity().length()))
  842. {
  843. position += symbols.getInfinity().length();
  844. status[STATUS_INFINITE] = true;
  845. } else {
  846. // We now have a string of digits, possibly with grouping symbols,
  847. // and decimal points. We want to process these into a DigitList.
  848. // We don't want to put a bunch of leading zeros into the DigitList
  849. // though, so we keep track of the location of the decimal point,
  850. // put only significant digits into the DigitList, and adjust the
  851. // exponent as needed.
  852. digits.decimalAt = digits.count = 0;
  853. char zero = symbols.getZeroDigit();
  854. char decimal = isCurrencyFormat ?
  855. symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator();
  856. char grouping = symbols.getGroupingSeparator();
  857. char exponentChar = symbols.getExponentialSymbol();
  858. boolean sawDecimal = false;
  859. boolean sawExponent = false;
  860. boolean sawDigit = false;
  861. int exponent = 0; // Set to the exponent value, if any
  862. // We have to track digitCount ourselves, because digits.count will
  863. // pin when the maximum allowable digits is reached.
  864. int digitCount = 0;
  865. backup = -1;
  866. for (; position < text.length(); ++position)
  867. {
  868. char ch = text.charAt(position);
  869. /* We recognize all digit ranges, not only the Latin digit range
  870. * '0'..'9'. We do so by using the Character.digit() method,
  871. * which converts a valid Unicode digit to the range 0..9.
  872. *
  873. * The character 'ch' may be a digit. If so, place its value
  874. * from 0 to 9 in 'digit'. First try using the locale digit,
  875. * which may or MAY NOT be a standard Unicode digit range. If
  876. * this fails, try using the standard Unicode digit ranges by
  877. * calling Character.digit(). If this also fails, digit will
  878. * have a value outside the range 0..9.
  879. */
  880. int digit = ch - zero;
  881. if (digit < 0 || digit > 9) digit = Character.digit(ch, 10);
  882. if (digit == 0)
  883. {
  884. // Cancel out backup setting (see grouping handler below)
  885. backup = -1; // Do this BEFORE continue statement below!!!
  886. sawDigit = true;
  887. // Handle leading zeros
  888. if (digits.count == 0)
  889. {
  890. // Ignore leading zeros in integer part of number.
  891. if (!sawDecimal) continue;
  892. // If we have seen the decimal, but no significant digits yet,
  893. // then we account for leading zeros by decrementing the
  894. // digits.decimalAt into negative values.
  895. --digits.decimalAt;
  896. }
  897. else
  898. {
  899. ++digitCount;
  900. digits.append((char)(digit + '0'));
  901. }
  902. }
  903. else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
  904. {
  905. sawDigit = true;
  906. ++digitCount;
  907. digits.append((char)(digit + '0'));
  908. // Cancel out backup setting (see grouping handler below)
  909. backup = -1;
  910. }
  911. else if (!isExponent && ch == decimal)
  912. {
  913. // If we're only parsing integers, or if we ALREADY saw the
  914. // decimal, then don't parse this one.
  915. if (isParseIntegerOnly() || sawDecimal) break;
  916. digits.decimalAt = digitCount; // Not digits.count!
  917. sawDecimal = true;
  918. }
  919. else if (!isExponent && ch == grouping && isGroupingUsed())
  920. {
  921. if (sawDecimal) {
  922. break;
  923. }
  924. // Ignore grouping characters, if we are using them, but require
  925. // that they be followed by a digit. Otherwise we backup and
  926. // reprocess them.
  927. backup = position;
  928. }
  929. else if (!isExponent && ch == exponentChar && !sawExponent)
  930. {
  931. // Process the exponent by recursively calling this method.
  932. ParsePosition pos = new ParsePosition(position + 1);
  933. boolean[] stat = new boolean[STATUS_LENGTH];
  934. DigitList exponentDigits = new DigitList();
  935. if (subparse(text, pos, exponentDigits, true, stat) &&
  936. exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true))
  937. {
  938. position = pos.index; // Advance past the exponent
  939. exponent = (int)exponentDigits.getLong();
  940. if (!stat[STATUS_POSITIVE]) exponent = -exponent;
  941. sawExponent = true;
  942. }
  943. break; // Whether we fail or succeed, we exit this loop
  944. }
  945. else break;
  946. }
  947. if (backup != -1) position = backup;
  948. // If there was no decimal point we have an integer
  949. if (!sawDecimal) digits.decimalAt = digitCount; // Not digits.count!
  950. // Adjust for exponent, if any
  951. digits.decimalAt += exponent;
  952. // If none of the text string was recognized. For example, parse
  953. // "x" with pattern "#0.00" (return index and error index both 0)
  954. // parse "$" with pattern "$#0.00". (return index 0 and error index
  955. // 1).
  956. if (!sawDigit && digitCount == 0) {
  957. parsePosition.index = oldStart;
  958. parsePosition.errorIndex = oldStart;
  959. return false;
  960. }
  961. }
  962. // check for positiveSuffix
  963. if (gotPositive)
  964. gotPositive = text.regionMatches(position,positiveSuffix,0,
  965. positiveSuffix.length());
  966. if (gotNegative)
  967. gotNegative = text.regionMatches(position,negativeSuffix,0,
  968. negativeSuffix.length());
  969. // if both match, take longest
  970. if (gotPositive && gotNegative) {
  971. if (positiveSuffix.length() > negativeSuffix.length())
  972. gotNegative = false;
  973. else if (positiveSuffix.length() < negativeSuffix.length())
  974. gotPositive = false;
  975. }
  976. // fail if neither or both
  977. if (gotPositive == gotNegative) {
  978. parsePosition.errorIndex = position;
  979. return false;
  980. }
  981. parsePosition.index = position +
  982. (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); // mark success!
  983. status[STATUS_POSITIVE] = gotPositive;
  984. if (parsePosition.index == oldStart) {
  985. parsePosition.errorIndex = position;
  986. return false;
  987. }
  988. return true;
  989. }
  990. /**
  991. * Returns the decimal format symbols, which is generally not changed
  992. * by the programmer or user.
  993. * @return desired DecimalFormatSymbols
  994. * @see java.text.DecimalFormatSymbols
  995. */
  996. public DecimalFormatSymbols getDecimalFormatSymbols() {
  997. try {
  998. // don't allow multiple references
  999. return (DecimalFormatSymbols) symbols.clone();
  1000. } catch (Exception foo) {
  1001. return null; // should never happen
  1002. }
  1003. }
  1004. /**
  1005. * Sets the decimal format symbols, which is generally not changed
  1006. * by the programmer or user.
  1007. * @param newSymbols desired DecimalFormatSymbols
  1008. * @see java.text.DecimalFormatSymbols
  1009. */
  1010. public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
  1011. try {
  1012. // don't allow multiple references
  1013. symbols = (DecimalFormatSymbols) newSymbols.clone();
  1014. expandAffixes();
  1015. } catch (Exception foo) {
  1016. // should never happen
  1017. }
  1018. }
  1019. /**
  1020. * Get the positive prefix.
  1021. * <P>Examples: +123, $123, sFr123
  1022. */
  1023. public String getPositivePrefix () {
  1024. return positivePrefix;
  1025. }
  1026. /**
  1027. * Set the positive prefix.
  1028. * <P>Examples: +123, $123, sFr123
  1029. */
  1030. public void setPositivePrefix (String newValue) {
  1031. positivePrefix = newValue;
  1032. posPrefixPattern = null;
  1033. }
  1034. /**
  1035. * Get the negative prefix.
  1036. * <P>Examples: -123, ($123) (with negative suffix), sFr-123
  1037. */
  1038. public String getNegativePrefix () {
  1039. return negativePrefix;
  1040. }
  1041. /**
  1042. * Set the negative prefix.
  1043. * <P>Examples: -123, ($123) (with negative suffix), sFr-123
  1044. */
  1045. public void setNegativePrefix (String newValue) {
  1046. negativePrefix = newValue;
  1047. negPrefixPattern = null;
  1048. }
  1049. /**
  1050. * Get the positive suffix.
  1051. * <P>Example: 123%
  1052. */
  1053. public String getPositiveSuffix () {
  1054. return positiveSuffix;
  1055. }
  1056. /**
  1057. * Set the positive suffix.
  1058. * <P>Example: 123%
  1059. */
  1060. public void setPositiveSuffix (String newValue) {
  1061. positiveSuffix = newValue;
  1062. posSuffixPattern = null;
  1063. }
  1064. /**
  1065. * Get the negative suffix.
  1066. * <P>Examples: -123%, ($123) (with positive suffixes)
  1067. */
  1068. public String getNegativeSuffix () {
  1069. return negativeSuffix;
  1070. }
  1071. /**
  1072. * Set the positive suffix.
  1073. * <P>Examples: 123%
  1074. */
  1075. public void setNegativeSuffix (String newValue) {
  1076. negativeSuffix = newValue;
  1077. negSuffixPattern = null;
  1078. }
  1079. /**
  1080. * Get the multiplier for use in percent, permill, etc.
  1081. * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
  1082. * (For Arabic, use arabic percent symbol).
  1083. * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
  1084. * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
  1085. */
  1086. public int getMultiplier () {
  1087. return multiplier;
  1088. }
  1089. /**
  1090. * Set the multiplier for use in percent, permill, etc.
  1091. * For a percentage, set the suffixes to have "%" and the multiplier to be 100.
  1092. * (For Arabic, use arabic percent symbol).
  1093. * For a permill, set the suffixes to have "\u2031" and the multiplier to be 1000.
  1094. * <P>Examples: with 100, 1.23 -> "123", and "123" -> 1.23
  1095. */
  1096. public void setMultiplier (int newValue) {
  1097. multiplier = newValue;
  1098. }
  1099. /**
  1100. * Return the grouping size. Grouping size is the number of digits between
  1101. * grouping separators in the integer portion of a number. For example,
  1102. * in the number "123,456.78", the grouping size is 3.
  1103. * @see #setGroupingSize
  1104. * @see java.text.NumberFormat#isGroupingUsed
  1105. * @see java.text.DecimalFormatSymbols#getGroupingSeparator
  1106. */
  1107. public int getGroupingSize () {
  1108. return groupingSize;
  1109. }
  1110. /**
  1111. * Set the grouping size. Grouping size is the number of digits between
  1112. * grouping separators in the integer portion of a number. For example,
  1113. * in the number "123,456.78", the grouping size is 3.
  1114. * @see #getGroupingSize
  1115. * @see java.text.NumberFormat#setGroupingUsed
  1116. * @see java.text.DecimalFormatSymbols#setGroupingSeparator
  1117. */
  1118. public void setGroupingSize (int newValue) {
  1119. groupingSize = (byte)newValue;
  1120. }
  1121. /**
  1122. * Allows you to get the behavior of the decimal separator with integers.
  1123. * (The decimal separator will always appear with decimals.)
  1124. * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
  1125. */
  1126. public boolean isDecimalSeparatorAlwaysShown() {
  1127. return decimalSeparatorAlwaysShown;
  1128. }
  1129. /**
  1130. * Allows you to set the behavior of the decimal separator with integers.
  1131. * (The decimal separator will always appear with decimals.)
  1132. * <P>Example: Decimal ON: 12345 -> 12345.; OFF: 12345 -> 12345
  1133. */
  1134. public void setDecimalSeparatorAlwaysShown(boolean newValue) {
  1135. decimalSeparatorAlwaysShown = newValue;
  1136. }
  1137. /**
  1138. * Standard override; no change in semantics.
  1139. */
  1140. public Object clone() {
  1141. try {
  1142. DecimalFormat other = (DecimalFormat) super.clone();
  1143. other.symbols = (DecimalFormatSymbols) symbols.clone();
  1144. return other;
  1145. } catch (Exception e) {
  1146. throw new InternalError();
  1147. }
  1148. }
  1149. /**
  1150. * Overrides equals
  1151. */
  1152. public boolean equals(Object obj)
  1153. {
  1154. if (obj == null) return false;
  1155. if (!super.equals(obj)) return false; // super does class check
  1156. DecimalFormat other = (DecimalFormat) obj;
  1157. return ((posPrefixPattern == other.posPrefixPattern &&
  1158. positivePrefix.equals(other.positivePrefix))
  1159. || (posPrefixPattern != null &&
  1160. posPrefixPattern.equals(other.posPrefixPattern)))
  1161. && ((posSuffixPattern == other.posSuffixPattern &&
  1162. positiveSuffix.equals(other.positiveSuffix))
  1163. || (posSuffixPattern != null &&
  1164. posSuffixPattern.equals(other.posSuffixPattern)))
  1165. && ((negPrefixPattern == other.negPrefixPattern &&
  1166. negativePrefix.equals(other.negativePrefix))
  1167. || (negPrefixPattern != null &&
  1168. negPrefixPattern.equals(other.negPrefixPattern)))
  1169. && ((negSuffixPattern == other.negSuffixPattern &&
  1170. negativeSuffix.equals(other.negativeSuffix))
  1171. || (negSuffixPattern != null &&
  1172. negSuffixPattern.equals(other.negSuffixPattern)))
  1173. && multiplier == other.multiplier
  1174. && groupingSize == other.groupingSize
  1175. && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown
  1176. && useExponentialNotation == other.useExponentialNotation
  1177. && (!useExponentialNotation ||
  1178. minExponentDigits == other.minExponentDigits)
  1179. && symbols.equals(other.symbols);
  1180. }
  1181. /**
  1182. * Overrides hashCode
  1183. */
  1184. public int hashCode() {
  1185. return super.hashCode() * 37 + positivePrefix.hashCode();
  1186. // just enough fields for a reasonable distribution
  1187. }
  1188. /**
  1189. * Synthesizes a pattern string that represents the current state
  1190. * of this Format object.
  1191. * @see #applyPattern
  1192. */
  1193. public String toPattern() {
  1194. return toPattern( false );
  1195. }
  1196. /**
  1197. * Synthesizes a localized pattern string that represents the current
  1198. * state of this Format object.
  1199. * @see #applyPattern
  1200. */
  1201. public String toLocalizedPattern() {
  1202. return toPattern( true );
  1203. }
  1204. /**
  1205. * Expand the affix pattern strings into the expanded affix strings. If any
  1206. * affix pattern string is null, do not expand it. This method should be
  1207. * called any time the symbols or the affix patterns change in order to keep
  1208. * the expanded affix strings up to date.
  1209. */
  1210. private void expandAffixes() {
  1211. // Reuse one StringBuffer for better performance
  1212. StringBuffer buffer = new StringBuffer();
  1213. if (posPrefixPattern != null) {
  1214. positivePrefix = expandAffix(posPrefixPattern, buffer);
  1215. }
  1216. if (posSuffixPattern != null) {
  1217. positiveSuffix = expandAffix(posSuffixPattern, buffer);
  1218. }
  1219. if (negPrefixPattern != null) {
  1220. negativePrefix = expandAffix(negPrefixPattern, buffer);
  1221. }
  1222. if (negSuffixPattern != null) {
  1223. negativeSuffix = expandAffix(negSuffixPattern, buffer);
  1224. }
  1225. }
  1226. /**
  1227. * Expand an affix pattern into an affix string. All characters in the
  1228. * pattern are literal unless prefixed by QUOTE. The following characters
  1229. * after QUOTE are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
  1230. * PATTERN_MINUS, and CURRENCY_SIGN. If CURRENCY_SIGN is doubled (QUOTE +
  1231. * CURRENCY_SIGN + CURRENCY_SIGN), it is interpreted as an international
  1232. * currency sign. Any other character after a QUOTE represents itself.
  1233. * QUOTE must be followed by another character; QUOTE may not occur by
  1234. * itself at the end of the pattern.
  1235. *
  1236. * @param pattern the non-null, possibly empty pattern
  1237. * @param buffer a scratch StringBuffer; its contents will be lost
  1238. * @return the expanded equivalent of pattern
  1239. */
  1240. private String expandAffix(String pattern, StringBuffer buffer) {
  1241. buffer.setLength(0);
  1242. for (int i=0; i<pattern.length(); ) {
  1243. char c = pattern.charAt(i++);
  1244. if (c == QUOTE) {
  1245. c = pattern.charAt(i++);
  1246. switch (c) {
  1247. case CURRENCY_SIGN:
  1248. if (i<pattern.length() &&
  1249. pattern.charAt(i) == CURRENCY_SIGN) {
  1250. ++i;
  1251. buffer.append(symbols.getInternationalCurrencySymbol());
  1252. } else {
  1253. buffer.append(symbols.getCurrencySymbol());
  1254. }
  1255. continue;
  1256. case PATTERN_PERCENT:
  1257. c = symbols.getPercent();
  1258. break;
  1259. case PATTERN_PER_MILLE:
  1260. c = symbols.getPerMill();
  1261. break;
  1262. case PATTERN_MINUS:
  1263. c = symbols.getMinusSign();
  1264. break;
  1265. }
  1266. }
  1267. buffer.append(c);
  1268. }
  1269. return buffer.toString();
  1270. }
  1271. /**
  1272. * Appends an affix pattern to the given StringBuffer, quoting special
  1273. * characters as needed. Uses the internal affix pattern, if that exists,
  1274. * or the literal affix, if the internal affix pattern is null. The
  1275. * appended string will generate the same affix pattern (or literal affix)
  1276. * when passed to toPattern().
  1277. *
  1278. * @param buffer the affix string is appended to this
  1279. * @param affixPattern a pattern such as posPrefixPattern; may be null
  1280. * @param expAffix a corresponding expanded affix, such as positivePrefix.
  1281. * Ignored unless affixPattern is null. If affixPattern is null, then
  1282. * expAffix is appended as a literal affix.
  1283. * @param localized true if the appended pattern should contain localized
  1284. * pattern characters; otherwise, non-localized pattern chars are appended
  1285. */
  1286. private void appendAffix(StringBuffer buffer, String affixPattern,
  1287. String expAffix, boolean localized) {
  1288. if (affixPattern == null) {
  1289. appendAffix(buffer, expAffix, localized);
  1290. } else {
  1291. int i;
  1292. for (int pos=0; pos<affixPattern.length(); pos=i) {
  1293. i = affixPattern.indexOf(QUOTE, pos);
  1294. if (i < 0) {
  1295. appendAffix(buffer, affixPattern.substring(pos), localized);
  1296. break;
  1297. }
  1298. if (i > pos) {
  1299. appendAffix(buffer, affixPattern.substring(pos, i), localized);
  1300. }
  1301. char c = affixPattern.charAt(++i);
  1302. ++i;
  1303. if (c == QUOTE) {
  1304. buffer.append(c);
  1305. // Fall through and append another QUOTE below
  1306. } else if (c == CURRENCY_SIGN &&
  1307. i<affixPattern.length() &&
  1308. affixPattern.charAt(i) == CURRENCY_SIGN) {
  1309. ++i;
  1310. buffer.append(c);
  1311. // Fall through and append another CURRENCY_SIGN below
  1312. } else if (localized) {
  1313. switch (c) {
  1314. case PATTERN_PERCENT:
  1315. c = symbols.getPercent();
  1316. break;
  1317. case PATTERN_PER_MILLE:
  1318. c = symbols.getPerMill();
  1319. break;
  1320. case PATTERN_MINUS:
  1321. c = symbols.getMinusSign();
  1322. break;
  1323. }
  1324. }
  1325. buffer.append(c);
  1326. }
  1327. }
  1328. }
  1329. /**
  1330. * Append an affix to the given StringBuffer, using quotes if
  1331. * there are special characters. Single quotes themselves must be
  1332. * escaped in either case.
  1333. */
  1334. private void appendAffix(StringBuffer buffer, String affix, boolean localized) {
  1335. boolean needQuote;
  1336. if (localized) {
  1337. needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
  1338. || affix.indexOf(symbols.getGroupingSeparator()) >= 0
  1339. || affix.indexOf(symbols.getDecimalSeparator()) >= 0
  1340. || affix.indexOf(symbols.getPercent()) >= 0
  1341. || affix.indexOf(symbols.getPerMill()) >= 0
  1342. || affix.indexOf(symbols.getDigit()) >= 0
  1343. || affix.indexOf(symbols.getPatternSeparator()) >= 0
  1344. || affix.indexOf(symbols.getMinusSign()) >= 0
  1345. || affix.indexOf(CURRENCY_SIGN) >= 0;
  1346. }
  1347. else {
  1348. needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
  1349. || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0
  1350. || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0
  1351. || affix.indexOf(PATTERN_PERCENT) >= 0
  1352. || affix.indexOf(PATTERN_PER_MILLE) >= 0
  1353. || affix.indexOf(PATTERN_DIGIT) >= 0
  1354. || affix.indexOf(PATTERN_SEPARATOR) >= 0
  1355. || affix.indexOf(PATTERN_MINUS) >= 0
  1356. || affix.indexOf(CURRENCY_SIGN) >= 0;
  1357. }
  1358. if (needQuote) buffer.append('\'');
  1359. if (affix.indexOf('\'') < 0) buffer.append(affix);
  1360. else {
  1361. for (int j=0; j<affix.length(); ++j) {
  1362. char c = affix.charAt(j);
  1363. buffer.append(c);
  1364. if (c == '\'') buffer.append(c);
  1365. }
  1366. }
  1367. if (needQuote) buffer.append('\'');
  1368. }
  1369. /**
  1370. * Does the real work of generating a pattern. */
  1371. private String toPattern(boolean localized) {
  1372. StringBuffer result = new StringBuffer();
  1373. for (int j = 1; j >= 0; --j) {
  1374. if (j == 1)
  1375. appendAffix(result, posPrefixPattern, positivePrefix, localized);
  1376. else appendAffix(result, negPrefixPattern, negativePrefix, localized);
  1377. int i;
  1378. int digitCount = useExponentialNotation
  1379. ? getMaximumIntegerDigits()
  1380. : Math.max(groupingSize, getMinimumIntegerDigits())+1;
  1381. for (i = digitCount; i > 0; --i) {
  1382. if (i != digitCount && isGroupingUsed() && groupingSize != 0 &&
  1383. i % groupingSize == 0) {
  1384. result.append(localized ? symbols.getGroupingSeparator() :
  1385. PATTERN_GROUPING_SEPARATOR);
  1386. }
  1387. result.append(i <= getMinimumIntegerDigits()
  1388. ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT)
  1389. : (localized ? symbols.getDigit() : PATTERN_DIGIT));
  1390. }
  1391. if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown)
  1392. result.append(localized ? symbols.getDecimalSeparator() :
  1393. PATTERN_DECIMAL_SEPARATOR);
  1394. for (i = 0; i < getMaximumFractionDigits(); ++i) {
  1395. if (i < getMinimumFractionDigits()) {
  1396. result.append(localized ? symbols.getZeroDigit() :
  1397. PATTERN_ZERO_DIGIT);
  1398. } else {
  1399. result.append(localized ? symbols.getDigit() :
  1400. PATTERN_DIGIT);
  1401. }
  1402. }
  1403. if (useExponentialNotation)
  1404. {
  1405. result.append(localized ? symbols.getExponentialSymbol() :
  1406. PATTERN_EXPONENT);
  1407. for (i=0; i<minExponentDigits; ++i)
  1408. result.append(localized ? symbols.getZeroDigit() :
  1409. PATTERN_ZERO_DIGIT);
  1410. }
  1411. if (j == 1) {
  1412. appendAffix(result, posSuffixPattern, positiveSuffix, localized);
  1413. if ((negSuffixPattern == posSuffixPattern && // n == p == null
  1414. negativeSuffix.equals(positiveSuffix))
  1415. || (negSuffixPattern != null &&
  1416. negSuffixPattern.equals(posSuffixPattern))) {
  1417. if ((negPrefixPattern != null && posPrefixPattern != null &&
  1418. negPrefixPattern.equals("'-" + posPrefixPattern)) ||
  1419. (negPrefixPattern == posPrefixPattern && // n == p == null
  1420. negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
  1421. break;
  1422. }
  1423. result.append(localized ? symbols.getPatternSeparator() :
  1424. PATTERN_SEPARATOR);
  1425. } else appendAffix(result, negSuffixPattern, negativeSuffix, localized);
  1426. }
  1427. return result.toString();
  1428. }
  1429. /**
  1430. * Apply the given pattern to this Format object. A pattern is a
  1431. * short-hand specification for the various formatting properties.
  1432. * These properties can also be changed individually through the
  1433. * various setter methods.
  1434. * <p>
  1435. * There is no limit to integer digits are set
  1436. * by this routine, since that is the typical end-user desire;
  1437. * use setMaximumInteger if you want to set a real value.
  1438. * For negative numbers, use a second pattern, separated by a semicolon
  1439. * <P>Example "#,#00.0#" -> 1,234.56
  1440. * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
  1441. * a maximum of 2 fraction digits.
  1442. * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
  1443. * <p>In negative patterns, the minimum and maximum counts are ignored;
  1444. * these are presumed to be set in the positive pattern.
  1445. */
  1446. public void applyPattern( String pattern ) {
  1447. applyPattern( pattern, false );
  1448. }
  1449. /**
  1450. * Apply the given pattern to this Format object. The pattern
  1451. * is assumed to be in a localized notation. A pattern is a
  1452. * short-hand specification for the various formatting properties.
  1453. * These properties can also be changed individually through the
  1454. * various setter methods.
  1455. * <p>
  1456. * There is no limit to integer digits are set
  1457. * by this routine, since that is the typical end-user desire;
  1458. * use setMaximumInteger if you want to set a real value.
  1459. * For negative numbers, use a second pattern, separated by a semicolon
  1460. * <P>Example "#,#00.0#" -> 1,234.56
  1461. * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
  1462. * a maximum of 2 fraction digits.
  1463. * <p>Example: "#,#00.0#;(#,#00.0#)" for negatives in parantheses.
  1464. * <p>In negative patterns, the minimum and maximum counts are ignored;
  1465. * these are presumed to be set in the positive pattern.
  1466. */
  1467. public void applyLocalizedPattern( String pattern ) {
  1468. applyPattern( pattern, true );
  1469. }
  1470. /**
  1471. * Does the real work of applying a pattern.
  1472. */
  1473. private void applyPattern(String pattern, boolean localized)
  1474. {
  1475. char zeroDigit = PATTERN_ZERO_DIGIT;
  1476. char groupingSeparator = PATTERN_GROUPING_SEPARATOR;
  1477. char decimalSeparator = PATTERN_DECIMAL_SEPARATOR;
  1478. char percent = PATTERN_PERCENT;
  1479. char perMill = PATTERN_PER_MILLE;
  1480. char digit = PATTERN_DIGIT;
  1481. char separator = PATTERN_SEPARATOR;
  1482. char exponent = PATTERN_EXPONENT;
  1483. char minus = PATTERN_MINUS;
  1484. if (localized) {
  1485. zeroDigit = symbols.getZeroDigit();
  1486. groupingSeparator = symbols.getGroupingSeparator();
  1487. decimalSeparator = symbols.getDecimalSeparator();
  1488. percent = symbols.getPercent();
  1489. perMill = symbols.getPerMill();
  1490. digit = symbols.getDigit();
  1491. separator = symbols.getPatternSeparator();
  1492. exponent = symbols.getExponentialSymbol();
  1493. minus = symbols.getMinusSign();
  1494. }
  1495. boolean gotNegative = false;
  1496. decimalSeparatorAlwaysShown = false;
  1497. isCurrencyFormat = false;
  1498. useExponentialNotation = false;
  1499. // Two variables are used to record the subrange of the pattern
  1500. // occupied by phase 1. This is used during the processing of the
  1501. // second pattern (the one representing negative numbers) to ensure
  1502. // that no deviation exists in phase 1 between the two patterns.
  1503. int phaseOneStart = 0;
  1504. int phaseOneLength = 0;
  1505. /** Back-out comment : HShih
  1506. * boolean phaseTwo = false;
  1507. */
  1508. int start = 0;
  1509. for (int j = 1; j >= 0 && start < pattern.length(); --j)
  1510. {
  1511. boolean inQuote = false;
  1512. StringBuffer prefix = new StringBuffer();
  1513. StringBuffer suffix = new StringBuffer();
  1514. int decimalPos = -1;
  1515. int multiplier = 1;
  1516. int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0;
  1517. byte groupingCount = -1;
  1518. // The phase ranges from 0 to 2. Phase 0 is the prefix. Phase 1 is
  1519. // the section of the pattern with digits, decimal separator,
  1520. // grouping characters. Phase 2 is the suffix. In phases 0 and 2,
  1521. // percent, permille, and currency symbols are recognized and
  1522. // translated. The separation of the characters into phases is
  1523. // strictly enforced; if phase 1 characters are to appear in the
  1524. // suffix, for example, they must be quoted.
  1525. int phase = 0;
  1526. // The affix is either the prefix or the suffix.
  1527. StringBuffer affix = prefix;
  1528. for (int pos = start; pos < pattern.length(); ++pos)
  1529. {
  1530. char ch = pattern.charAt(pos);
  1531. switch (phase)
  1532. {
  1533. case 0:
  1534. case 2:
  1535. // Process the prefix / suffix characters
  1536. if (inQuote)
  1537. {
  1538. // A quote within quotes indicates either the closing
  1539. // quote or two quotes, which is a quote literal. That is,
  1540. // we have the second quote in 'do' or 'don''t'.
  1541. if (ch == QUOTE)
  1542. {
  1543. if ((pos+1) < pattern.length() &&
  1544. pattern.charAt(pos+1) == QUOTE)
  1545. {
  1546. ++pos;
  1547. affix.append("''"); // 'don''t'
  1548. }
  1549. else
  1550. {
  1551. inQuote = false; // 'do'
  1552. }
  1553. continue;
  1554. }
  1555. }
  1556. else
  1557. {
  1558. // Process unquoted characters seen in prefix or suffix
  1559. // phase.
  1560. if (ch == digit ||
  1561. ch == zeroDigit ||
  1562. ch == groupingSeparator ||
  1563. ch == decimalSeparator)
  1564. {
  1565. // Any of these characters implicitly begins the next
  1566. // phase. If we are in phase 2, there is no next phase,
  1567. // so these characters are illegal.
  1568. /**
  1569. * 1.2 Back-out comment : HShih
  1570. * Can't throw exception here.
  1571. * if (phase == 2)
  1572. * throw new IllegalArgumentException("Unquoted special character '" +
  1573. * ch + "' in pattern \"" +
  1574. * pattern + '"');
  1575. */
  1576. phase = 1;
  1577. if (j == 1) phaseOneStart = pos;
  1578. --pos; // Reprocess this character
  1579. continue;
  1580. }
  1581. else if (ch == CURRENCY_SIGN)
  1582. {
  1583. // Use lookahead to determine if the currency sign is
  1584. // doubled or not.
  1585. boolean doubled = (pos + 1) < pattern.length() &&
  1586. pattern.charAt(pos + 1) == CURRENCY_SIGN;
  1587. if (doubled) ++pos; // Skip over the doubled character
  1588. isCurrencyFormat = true;
  1589. affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4");
  1590. continue;
  1591. }
  1592. else if (ch == QUOTE)
  1593. {
  1594. // A quote outside quotes indicates either the opening
  1595. // quote or two quotes, which is a quote literal. That is,
  1596. // we have the first quote in 'do' or o''clock.
  1597. if (ch == QUOTE)
  1598. {
  1599. if ((pos+1) < pattern.length() &&
  1600. pattern.charAt(pos+1) == QUOTE)
  1601. {
  1602. ++pos;
  1603. affix.append("''"); // o''clock
  1604. }
  1605. else
  1606. {
  1607. inQuote = true; // 'do'
  1608. }
  1609. continue;
  1610. }
  1611. }
  1612. else if (ch == separator)
  1613. {
  1614. // Don't allow separators before we see digit characters of phase
  1615. // 1, and don't allow separators in the second pattern (j == 0).
  1616. if (phase == 0 || j == 0)
  1617. throw new IllegalArgumentException("Unquoted special character '" +
  1618. ch + "' in pattern \"" +
  1619. pattern + '"');
  1620. start = pos + 1;
  1621. pos = pattern.length();
  1622. continue;
  1623. }
  1624. // Next handle characters which are appended directly.
  1625. else if (ch == percent)
  1626. {
  1627. if (multiplier != 1)
  1628. throw new IllegalArgumentException("Too many percent/permille characters in pattern \"" +
  1629. pattern + '"');
  1630. multiplier = 100;
  1631. affix.append("'%");
  1632. continue;
  1633. }
  1634. else if (ch == perMill)
  1635. {
  1636. if (multiplier != 1)
  1637. throw new IllegalArgumentException("Too many percent/permille characters in pattern \"" +
  1638. pattern + '"');
  1639. multiplier = 1000;
  1640. affix.append("'\u2030");
  1641. continue;
  1642. } else if (ch == minus) {
  1643. affix.append("'-");
  1644. continue;
  1645. }
  1646. }
  1647. // Note that if we are within quotes, or if this is an unquoted,
  1648. // non-special character, then we usually fall through to here.
  1649. affix.append(ch);
  1650. break;
  1651. case 1:
  1652. // Phase one must be identical in the two sub-patterns. We
  1653. // enforce this by doing a direct comparison. While
  1654. // processing the first sub-pattern, we just record its
  1655. // length. While processing the second, we compare
  1656. // characters.
  1657. if (j == 1) ++phaseOneLength;
  1658. else
  1659. {
  1660. /**
  1661. * 1.2 Back-out comment : HShih
  1662. * if (ch != pattern.charAt(phaseOneStart++))
  1663. * throw new IllegalArgumentException("Subpattern mismatch in \"" +
  1664. * pattern + '"');
  1665. * phaseTwo = true;
  1666. */
  1667. if (--phaseOneLength == 0)
  1668. {
  1669. phase = 2;
  1670. affix = suffix;
  1671. }
  1672. continue;
  1673. }
  1674. // Process the digits, decimal, and grouping characters. We
  1675. // record five pieces of information. We expect the digits
  1676. // to occur in the pattern ####0000.####, and we record the
  1677. // number of left digits, zero (central) digits, and right
  1678. // digits. The position of the last grouping character is
  1679. // recorded (should be somewhere within the first two blocks
  1680. // of characters), as is the position of the decimal point,
  1681. // if any (should be in the zero digits). If there is no
  1682. // decimal point, then there should be no right digits.
  1683. if (ch == digit)
  1684. {
  1685. if (zeroDigitCount > 0) ++digitRightCount; else ++digitLeftCount;
  1686. if (groupingCount >= 0 && decimalPos < 0) ++groupingCount;
  1687. }
  1688. else if (ch == zeroDigit)
  1689. {
  1690. if (digitRightCount > 0)
  1691. throw new IllegalArgumentException("Unexpected '0' in pattern \"" +
  1692. pattern + '"');
  1693. ++zeroDigitCount;
  1694. if (groupingCount >= 0 && decimalPos < 0) ++groupingCount;
  1695. }
  1696. else if (ch == groupingSeparator)
  1697. {
  1698. groupingCount = 0;
  1699. }
  1700. else if (ch == decimalSeparator)
  1701. {
  1702. if (decimalPos >= 0)
  1703. throw new IllegalArgumentException("Multiple decimal separators in pattern \"" +
  1704. pattern + '"');
  1705. decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
  1706. }
  1707. else if (ch == exponent)
  1708. {
  1709. if (useExponentialNotation)
  1710. throw new IllegalArgumentException("Multiple exponential " +
  1711. "symbols in pattern \"" +
  1712. pattern + '"');
  1713. useExponentialNotation = true;
  1714. minExponentDigits = 0;
  1715. // Use lookahead to parse out the exponential part of the
  1716. // pattern, then jump into phase 2.
  1717. while (++pos < pattern.length() &&
  1718. pattern.charAt(pos) == zeroDigit)
  1719. {
  1720. ++minExponentDigits;
  1721. ++phaseOneLength;
  1722. }
  1723. if ((digitLeftCount + zeroDigitCount) < 1 ||
  1724. minExponentDigits < 1)
  1725. throw new IllegalArgumentException("Malformed exponential " +
  1726. "pattern \"" +
  1727. pattern + '"');
  1728. // Transition to phase 2
  1729. phase = 2;
  1730. affix = suffix;
  1731. --pos;
  1732. continue;
  1733. }
  1734. else
  1735. {
  1736. phase = 2;
  1737. affix = suffix;
  1738. --pos;
  1739. --phaseOneLength;
  1740. continue;
  1741. }
  1742. break;
  1743. }
  1744. }
  1745. /**
  1746. * 1.2 Back-out comment : HShih
  1747. * if (phaseTwo && phaseOneLength > 0)
  1748. * throw new IllegalArgumentException("Subpattern mismatch in \"" +
  1749. * pattern + '"');
  1750. */
  1751. // Handle patterns with no '0' pattern character. These patterns
  1752. // are legal, but must be interpreted. "##.###" -> "#0.###".
  1753. // ".###" -> ".0##".
  1754. /* We allow patterns of the form "####" to produce a zeroDigitCount of
  1755. * zero (got that?); although this seems like it might make it possible
  1756. * for format() to produce empty strings, format() checks for this
  1757. * condition and outputs a zero digit in this situation. Having a
  1758. * zeroDigitCount of zero yields a minimum integer digits of zero, which
  1759. * allows proper round-trip patterns. That is, we don't want "#" to
  1760. * become "#0" when toPattern() is called (even though that's what it
  1761. * really is, semantically). */
  1762. if (zeroDigitCount == 0 && digitLeftCount > 0 &&
  1763. decimalPos >= 0) {
  1764. // Handle "###.###" and "###." and ".###"
  1765. int n = decimalPos;
  1766. if (n == 0) ++n; // Handle ".###"
  1767. digitRightCount = digitLeftCount - n;
  1768. digitLeftCount = n - 1;
  1769. zeroDigitCount = 1;
  1770. }
  1771. // Do syntax checking on the digits.
  1772. if ((decimalPos < 0 && digitRightCount > 0) ||
  1773. (decimalPos >= 0 &&
  1774. (decimalPos < digitLeftCount ||
  1775. decimalPos > (digitLeftCount + zeroDigitCount))) ||
  1776. groupingCount == 0 ||
  1777. inQuote)
  1778. throw new IllegalArgumentException("Malformed pattern \"" +
  1779. pattern + '"');
  1780. if (j == 1) {
  1781. posPrefixPattern = prefix.toString();
  1782. posSuffixPattern = suffix.toString();
  1783. negPrefixPattern = posPrefixPattern; // assume these for now
  1784. negSuffixPattern = posSuffixPattern;
  1785. int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount;
  1786. /* The effectiveDecimalPos is the position the decimal is at or
  1787. * would be at if there is no decimal. Note that if decimalPos<0,
  1788. * then digitTotalCount == digitLeftCount + zeroDigitCount. */
  1789. int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount;
  1790. setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount);
  1791. setMaximumIntegerDigits(useExponentialNotation ?
  1792. digitLeftCount + getMinimumIntegerDigits() : DOUBLE_INTEGER_DIGITS);
  1793. setMaximumFractionDigits(decimalPos >= 0 ? (digitTotalCount - decimalPos) : 0);
  1794. setMinimumFractionDigits(decimalPos >= 0 ?
  1795. (digitLeftCount + zeroDigitCount - decimalPos) : 0);
  1796. setGroupingUsed(groupingCount > 0);
  1797. this.groupingSize = (groupingCount > 0) ? groupingCount : 0;
  1798. this.multiplier = multiplier;
  1799. setDecimalSeparatorAlwaysShown(decimalPos == 0 || decimalPos == digitTotalCount);
  1800. } else {
  1801. negPrefixPattern = prefix.toString();
  1802. negSuffixPattern = suffix.toString();
  1803. gotNegative = true;
  1804. }
  1805. }
  1806. if (pattern.length() == 0) {
  1807. posPrefixPattern = posSuffixPattern = "";
  1808. setMinimumIntegerDigits(0);
  1809. setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS);
  1810. setMinimumFractionDigits(0);
  1811. setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS);
  1812. }
  1813. // If there was no negative pattern, or if the negative pattern is identical
  1814. // to the positive pattern, then prepend the minus sign to the positive
  1815. // pattern to form the negative pattern.
  1816. if (!gotNegative ||
  1817. (negPrefixPattern.equals(posPrefixPattern)
  1818. && negSuffixPattern.equals(posSuffixPattern))) {
  1819. negSuffixPattern = posSuffixPattern;
  1820. negPrefixPattern = "'-" + posPrefixPattern;
  1821. }
  1822. expandAffixes();
  1823. }
  1824. /**
  1825. * Sets the maximum number of digits allowed in the integer portion of a
  1826. * number. This override limits the integer digit count to 309.
  1827. * @see NumberFormat#setMaximumIntegerDigits
  1828. */
  1829. public void setMaximumIntegerDigits(int newValue) {
  1830. super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
  1831. }
  1832. /**
  1833. * Sets the minimum number of digits allowed in the integer portion of a
  1834. * number. This override limits the integer digit count to 309.
  1835. * @see NumberFormat#setMinimumIntegerDigits
  1836. */
  1837. public void setMinimumIntegerDigits(int newValue) {
  1838. super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS));
  1839. }
  1840. /**
  1841. * Sets the maximum number of digits allowed in the fraction portion of a
  1842. * number. This override limits the fraction digit count to 340.
  1843. * @see NumberFormat#setMaximumFractionDigits
  1844. */
  1845. public void setMaximumFractionDigits(int newValue) {
  1846. super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
  1847. }
  1848. /**
  1849. * Sets the minimum number of digits allowed in the fraction portion of a
  1850. * number. This override limits the fraction digit count to 340.
  1851. * @see NumberFormat#setMinimumFractionDigits
  1852. */
  1853. public void setMinimumFractionDigits(int newValue) {
  1854. super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS));
  1855. }
  1856. /**
  1857. * First, read the default serializable fields from the stream. Then
  1858. * if <code>serialVersionOnStream</code> is less than 1, indicating that
  1859. * the stream was written by JDK 1.1, initialize <code>useExponentialNotation</code>
  1860. * to false, since it was not present in JDK 1.1.
  1861. * Finally, set serialVersionOnStream back to the maximum allowed value so that
  1862. * default serialization will work properly if this object is streamed out again.
  1863. *
  1864. * <p>If the minimum or maximum integer digit count is larger than
  1865. * <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or maximum fraction
  1866. * digit count is larger than <code>DOUBLE_FRACTION_DIGITS</code>, then the
  1867. * stream data is invalid and this method throws an
  1868. * <code>InvalidObjectException</code>.
  1869. *
  1870. * <p>Stream versions older than 2 will not have the affix pattern variables
  1871. * <code>posPrefixPattern</code> etc. As a result, they will be initialized
  1872. * to <code>null</code>, which means the affix strings will be taken as
  1873. * literal values. This is exactly what we want, since that corresponds to
  1874. * the pre-version-2 behavior.
  1875. */
  1876. private void readObject(ObjectInputStream stream)
  1877. throws IOException, ClassNotFoundException
  1878. {
  1879. stream.defaultReadObject();
  1880. // We only need to check the maximum counts because NumberFormat
  1881. // .readObject has already ensured that the maximum is greater than the
  1882. // minimum count.
  1883. if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS ||
  1884. getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) {
  1885. throw new InvalidObjectException("Digit count out of range");
  1886. }
  1887. if (serialVersionOnStream < 1) {
  1888. // Didn't have exponential fields
  1889. useExponentialNotation = false;
  1890. }
  1891. serialVersionOnStream = currentSerialVersion;
  1892. digitList = new DigitList();
  1893. }
  1894. //----------------------------------------------------------------------
  1895. // INSTANCE VARIABLES
  1896. //----------------------------------------------------------------------
  1897. private transient DigitList digitList = new DigitList();
  1898. /**
  1899. * The symbol used as a prefix when formatting positive numbers, e.g. "+".
  1900. *
  1901. * @serial
  1902. * @see #getPositivePrefix
  1903. */
  1904. private String positivePrefix = "";
  1905. /**
  1906. * The symbol used as a suffix when formatting positive numbers.
  1907. * This is often an empty string.
  1908. *
  1909. * @serial
  1910. * @see #getPositiveSuffix
  1911. */
  1912. private String positiveSuffix = "";
  1913. /**
  1914. * The symbol used as a prefix when formatting negative numbers, e.g. "-".
  1915. *
  1916. * @serial
  1917. * @see #getNegativePrefix
  1918. */
  1919. private String negativePrefix = "-";
  1920. /**
  1921. * The symbol used as a suffix when formatting negative numbers.
  1922. * This is often an empty string.
  1923. *
  1924. * @serial
  1925. * @see #getNegativeSuffix
  1926. */
  1927. private String negativeSuffix = "";
  1928. /**
  1929. * The prefix pattern for non-negative numbers. This variable corresponds
  1930. * to <code>positivePrefix</code>.
  1931. *
  1932. * <p>This pattern is expanded by the method <code>expandAffix()</code> to
  1933. * <code>positivePrefix</code> to update the latter to reflect changes in
  1934. * <code>symbols</code>. If this variable is <code>null</code> then
  1935. * <code>positivePrefix</code> is taken as a literal value that does not
  1936. * change when <code>symbols</code> changes. This variable is always
  1937. * <code>null</code> for <code>DecimalFormat</code> objects older than
  1938. * stream version 2 restored from stream.
  1939. *
  1940. * @serial
  1941. * @since 1.3
  1942. * @see #positivePrefix
  1943. * @see #expandAffix
  1944. */
  1945. private String posPrefixPattern;
  1946. /**
  1947. * The suffix pattern for non-negative numbers. This variable corresponds
  1948. * to <code>positiveSuffix</code>. This variable is analogous to
  1949. * <code>posPrefixPattern</code> see that variable for further
  1950. * documentation.
  1951. *
  1952. * @serial
  1953. * @since 1.3
  1954. * @see #positiveSuffix
  1955. * @see #posPrefixPattern
  1956. */
  1957. private String posSuffixPattern;
  1958. /**
  1959. * The prefix pattern for negative numbers. This variable corresponds
  1960. * to <code>negativePrefix</code>. This variable is analogous to
  1961. * <code>posPrefixPattern</code> see that variable for further
  1962. * documentation.
  1963. *
  1964. * @serial
  1965. * @since 1.3
  1966. * @see #negativePrefix
  1967. * @see #posPrefixPattern
  1968. */
  1969. private String negPrefixPattern;
  1970. /**
  1971. * The suffix pattern for negative numbers. This variable corresponds
  1972. * to <code>negativeSuffix</code>. This variable is analogous to
  1973. * <code>posPrefixPattern</code> see that variable for further
  1974. * documentation.
  1975. *
  1976. * @serial
  1977. * @since 1.3
  1978. * @see #negativeSuffix
  1979. * @see #posPrefixPattern
  1980. */
  1981. private String negSuffixPattern;
  1982. /**
  1983. * The multiplier for use in percent, permill, etc.
  1984. *
  1985. * @serial
  1986. * @see #getMultiplier
  1987. */
  1988. private int multiplier = 1;
  1989. /**
  1990. * The number of digits between grouping separators in the integer
  1991. * portion of a number. Must be greater than 0 if
  1992. * <code>NumberFormat.groupingUsed</code> is true.
  1993. *
  1994. * @serial
  1995. * @see #getGroupingSize
  1996. * @see java.text.NumberFormat#isGroupingUsed
  1997. */
  1998. private byte groupingSize = 3; // invariant, > 0 if useThousands
  1999. /**
  2000. * If true, forces the decimal separator to always appear in a formatted
  2001. * number, even if the fractional part of the number is zero.
  2002. *
  2003. * @serial
  2004. * @see #isDecimalSeparatorAlwaysShown
  2005. */
  2006. private boolean decimalSeparatorAlwaysShown = false;
  2007. /**
  2008. * True if this object represents a currency format. This determines
  2009. * whether the monetary decimal separator is used instead of the normal one.
  2010. */
  2011. private transient boolean isCurrencyFormat = false;
  2012. /**
  2013. * The <code>DecimalFormatSymbols</code> object used by this format.
  2014. * It contains the symbols used to format numbers, e.g. the grouping separator,
  2015. * decimal separator, and so on.
  2016. *
  2017. * @serial
  2018. * @see #setDecimalFormatSymbols
  2019. * @see java.text.DecimalFormatSymbols
  2020. */
  2021. private DecimalFormatSymbols symbols = null; // LIU new DecimalFormatSymbols();
  2022. /**
  2023. * True to force the use of exponential (i.e. scientific) notation when formatting
  2024. * numbers.
  2025. *
  2026. * @serial
  2027. * @since 1.2
  2028. */
  2029. private boolean useExponentialNotation; // Newly persistent in the Java 2 platform
  2030. /**
  2031. * The minimum number of digits used to display the exponent when a number is
  2032. * formatted in exponential notation. This field is ignored if
  2033. * <code>useExponentialNotation</code> is not true.
  2034. *
  2035. * @serial
  2036. * @since 1.2
  2037. */
  2038. private byte minExponentDigits; // Newly persistent in the Java 2 platform
  2039. //----------------------------------------------------------------------
  2040. static final int currentSerialVersion = 2;
  2041. /**
  2042. * The internal serial version which says which version was written
  2043. * Possible values are:
  2044. * <ul>
  2045. * <li><b>0</b> (default): versions before the Java 2 platform v1.2
  2046. * <li><b>1</b>: version for 1.2, which includes the two new fields
  2047. * <code>useExponentialNotation</code> and <code>minExponentDigits</code>.
  2048. * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
  2049. * <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
  2050. * <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
  2051. * </ul>
  2052. * @since 1.2
  2053. * @serial
  2054. */
  2055. private int serialVersionOnStream = currentSerialVersion;
  2056. //----------------------------------------------------------------------
  2057. // CONSTANTS
  2058. //----------------------------------------------------------------------
  2059. // Constants for characters used in programmatic (unlocalized) patterns.
  2060. private static final char PATTERN_ZERO_DIGIT = '0';
  2061. private static final char PATTERN_GROUPING_SEPARATOR = ',';
  2062. private static final char PATTERN_DECIMAL_SEPARATOR = '.';
  2063. private static final char PATTERN_PER_MILLE = '\u2030';
  2064. private static final char PATTERN_PERCENT = '%';
  2065. private static final char PATTERN_DIGIT = '#';
  2066. private static final char PATTERN_SEPARATOR = ';';
  2067. private static final char PATTERN_EXPONENT = 'E';
  2068. private static final char PATTERN_MINUS = '-';
  2069. /**
  2070. * The CURRENCY_SIGN is the standard Unicode symbol for currency. It
  2071. * is used in patterns and substitued with either the currency symbol,
  2072. * or if it is doubled, with the international currency symbol. If the
  2073. * CURRENCY_SIGN is seen in a pattern, then the decimal separator is
  2074. * replaced with the monetary decimal separator.
  2075. *
  2076. * The CURRENCY_SIGN is not localized.
  2077. */
  2078. private static final char CURRENCY_SIGN = '\u00A4';
  2079. private static final char QUOTE = '\'';
  2080. // Upper limit on integer and fraction digits for a Java double
  2081. static final int DOUBLE_INTEGER_DIGITS = 309;
  2082. static final int DOUBLE_FRACTION_DIGITS = 340;
  2083. // Proclaim JDK 1.1 serial compatibility.
  2084. static final long serialVersionUID = 864413376551465018L;
  2085. /**
  2086. * Cache to hold the NumberPattern of a Locale.
  2087. */
  2088. private static Hashtable cachedLocaleData = new Hashtable(3);
  2089. }
  2090. //eof