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