OLD | NEW |
1 // © 2017 and later: Unicode, Inc. and others. | 1 // © 2017 and later: Unicode, Inc. and others. |
2 // License & terms of use: http://www.unicode.org/copyright.html#License | 2 // License & terms of use: http://www.unicode.org/copyright.html#License |
3 package com.ibm.icu.text; | 3 package com.ibm.icu.text; |
4 | 4 |
5 import java.io.IOException; | 5 import java.io.IOException; |
6 import java.io.ObjectInputStream; | 6 import java.io.ObjectInputStream; |
7 import java.io.ObjectOutputStream; | 7 import java.io.ObjectOutputStream; |
8 import java.io.ObjectStreamField; | 8 import java.io.ObjectStreamField; |
9 import java.math.BigInteger; | 9 import java.math.BigInteger; |
10 import java.math.RoundingMode; | 10 import java.math.RoundingMode; |
11 import java.text.AttributedCharacterIterator; | 11 import java.text.AttributedCharacterIterator; |
12 import java.text.FieldPosition; | 12 import java.text.FieldPosition; |
13 import java.text.ParseException; | |
14 import java.text.ParsePosition; | 13 import java.text.ParsePosition; |
15 | 14 |
16 import com.ibm.icu.impl.number.AffixUtils; | 15 import com.ibm.icu.impl.number.AffixUtils; |
17 import com.ibm.icu.impl.number.DecimalFormatProperties; | 16 import com.ibm.icu.impl.number.DecimalFormatProperties; |
18 import com.ibm.icu.impl.number.Padder.PadPosition; | 17 import com.ibm.icu.impl.number.Padder.PadPosition; |
19 import com.ibm.icu.impl.number.Parse; | 18 import com.ibm.icu.impl.number.Parse; |
20 import com.ibm.icu.impl.number.PatternStringParser; | 19 import com.ibm.icu.impl.number.PatternStringParser; |
21 import com.ibm.icu.impl.number.PatternStringUtils; | 20 import com.ibm.icu.impl.number.PatternStringUtils; |
| 21 import com.ibm.icu.impl.number.parse.NumberParserImpl; |
| 22 import com.ibm.icu.impl.number.parse.ParsedNumber; |
22 import com.ibm.icu.lang.UCharacter; | 23 import com.ibm.icu.lang.UCharacter; |
23 import com.ibm.icu.math.BigDecimal; | 24 import com.ibm.icu.math.BigDecimal; |
24 import com.ibm.icu.math.MathContext; | 25 import com.ibm.icu.math.MathContext; |
25 import com.ibm.icu.number.FormattedNumber; | 26 import com.ibm.icu.number.FormattedNumber; |
26 import com.ibm.icu.number.LocalizedNumberFormatter; | 27 import com.ibm.icu.number.LocalizedNumberFormatter; |
27 import com.ibm.icu.number.NumberFormatter; | 28 import com.ibm.icu.number.NumberFormatter; |
28 import com.ibm.icu.text.PluralRules.IFixedDecimal; | 29 import com.ibm.icu.text.PluralRules.IFixedDecimal; |
29 import com.ibm.icu.util.Currency; | 30 import com.ibm.icu.util.Currency; |
30 import com.ibm.icu.util.Currency.CurrencyUsage; | 31 import com.ibm.icu.util.Currency.CurrencyUsage; |
31 import com.ibm.icu.util.CurrencyAmount; | 32 import com.ibm.icu.util.CurrencyAmount; |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 * threads may read and write at the same time. | 271 * threads may read and write at the same time. |
271 */ | 272 */ |
272 transient volatile LocalizedNumberFormatter formatter; | 273 transient volatile LocalizedNumberFormatter formatter; |
273 | 274 |
274 /** | 275 /** |
275 * The effective properties as exported from the formatter object. Volatile be
cause threads may | 276 * The effective properties as exported from the formatter object. Volatile be
cause threads may |
276 * read and write at the same time. | 277 * read and write at the same time. |
277 */ | 278 */ |
278 transient volatile DecimalFormatProperties exportedProperties; | 279 transient volatile DecimalFormatProperties exportedProperties; |
279 | 280 |
| 281 transient volatile NumberParserImpl parser; |
| 282 transient volatile NumberParserImpl parserWithCurrency; |
| 283 |
280 //============================================================================
=========// | 284 //============================================================================
=========// |
281 // CONSTRUCTORS
// | 285 // CONSTRUCTORS
// |
282 //============================================================================
=========// | 286 //============================================================================
=========// |
283 | 287 |
284 /** | 288 /** |
285 * Creates a DecimalFormat based on the number pattern and symbols for the def
ault locale. This is | 289 * Creates a DecimalFormat based on the number pattern and symbols for the def
ault locale. This is |
286 * a convenient way to obtain a DecimalFormat instance when internationalizati
on is not the main | 290 * a convenient way to obtain a DecimalFormat instance when internationalizati
on is not the main |
287 * concern. | 291 * concern. |
288 * | 292 * |
289 * <p>Most users should call the factory methods on NumberFormat, such as {@li
nk | 293 * <p>Most users should call the factory methods on NumberFormat, such as {@li
nk |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 return toAppendTo; | 783 return toAppendTo; |
780 } | 784 } |
781 | 785 |
782 /** | 786 /** |
783 * {@inheritDoc} | 787 * {@inheritDoc} |
784 * | 788 * |
785 * @stable ICU 2.0 | 789 * @stable ICU 2.0 |
786 */ | 790 */ |
787 @Override | 791 @Override |
788 public Number parse(String text, ParsePosition parsePosition) { | 792 public Number parse(String text, ParsePosition parsePosition) { |
789 DecimalFormatProperties pprops = threadLocalProperties.get(); | 793 if (text == null) { |
790 synchronized (this) { | 794 throw new IllegalArgumentException("Text cannot be null"); |
791 pprops.copyFrom(properties); | 795 } |
792 } | 796 if (parsePosition == null) { |
793 // Backwards compatibility: use currency parse mode if this is a currency in
stance | 797 parsePosition = new ParsePosition(0); |
794 Number result = Parse.parse(text, parsePosition, pprops, symbols); | 798 } |
795 // Backwards compatibility: return com.ibm.icu.math.BigDecimal | 799 |
796 if (result instanceof java.math.BigDecimal) { | 800 ParsedNumber result = new ParsedNumber(); |
797 result = safeConvertBigDecimal((java.math.BigDecimal) result); | 801 // Note: if this is a currency instance, currencies will be matched despit
e the fact that we are not in the |
798 } | 802 // parseCurrency method (backwards compatibility) |
799 return result; | 803 int startIndex = parsePosition.getIndex(); |
| 804 parser.parse(text, startIndex, true, result); |
| 805 if (result.success()) { |
| 806 parsePosition.setIndex(startIndex + result.charsConsumed); |
| 807 // TODO: Accessing properties here is technically not thread-safe |
| 808 Number number = result.getNumber(properties.getParseToBigDecimal()); |
| 809 // Backwards compatibility: return com.ibm.icu.math.BigDecimal |
| 810 if (number instanceof java.math.BigDecimal) { |
| 811 number = safeConvertBigDecimal((java.math.BigDecimal) number); |
| 812 } |
| 813 return number; |
| 814 } else { |
| 815 parsePosition.setErrorIndex(startIndex + result.charsConsumed); |
| 816 return null; |
| 817 } |
800 } | 818 } |
801 | 819 |
802 /** | 820 /** |
803 * {@inheritDoc} | 821 * {@inheritDoc} |
804 * | 822 * |
805 * @stable ICU 49 | 823 * @stable ICU 49 |
806 */ | 824 */ |
807 @Override | 825 @Override |
808 public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosi
tion) { | 826 public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosi
tion) { |
809 try { | 827 if (text == null) { |
810 DecimalFormatProperties pprops = threadLocalProperties.get(); | 828 throw new IllegalArgumentException("Text cannot be null"); |
811 synchronized (this) { | |
812 pprops.copyFrom(properties); | |
813 } | 829 } |
814 CurrencyAmount result = Parse.parseCurrency(text, parsePosition, pprops, s
ymbols); | 830 if (parsePosition == null) { |
815 if (result == null) return null; | 831 parsePosition = new ParsePosition(0); |
816 Number number = result.getNumber(); | |
817 // Backwards compatibility: return com.ibm.icu.math.BigDecimal | |
818 if (number instanceof java.math.BigDecimal) { | |
819 number = safeConvertBigDecimal((java.math.BigDecimal) number); | |
820 result = new CurrencyAmount(number, result.getCurrency()); | |
821 } | 832 } |
822 return result; | 833 |
823 } catch (ParseException e) { | 834 ParsedNumber result = new ParsedNumber(); |
824 return null; | 835 int startIndex = parsePosition.getIndex(); |
825 } | 836 parserWithCurrency.parse(text.toString(), startIndex, true, result); |
| 837 if (result.success()) { |
| 838 parsePosition.setIndex(startIndex + result.charsConsumed); |
| 839 // TODO: Accessing properties here is technically not thread-safe |
| 840 Number number = result.getNumber(properties.getParseToBigDecimal()); |
| 841 // Backwards compatibility: return com.ibm.icu.math.BigDecimal |
| 842 if (number instanceof java.math.BigDecimal) { |
| 843 number = safeConvertBigDecimal((java.math.BigDecimal) number); |
| 844 } |
| 845 Currency currency = Currency.getInstance(result.currencyCode); |
| 846 return new CurrencyAmount(number, currency); |
| 847 } else { |
| 848 parsePosition.setErrorIndex(startIndex + result.charsConsumed); |
| 849 return null; |
| 850 } |
826 } | 851 } |
827 | 852 |
828 //============================================================================
=========// | 853 //============================================================================
=========// |
829 // GETTERS AND SETTERS
// | 854 // GETTERS AND SETTERS
// |
830 //============================================================================
=========// | 855 //============================================================================
=========// |
831 | 856 |
832 /** | 857 /** |
833 * Returns a copy of the decimal format symbols used by this formatter. | 858 * Returns a copy of the decimal format symbols used by this formatter. |
834 * | 859 * |
835 * @return desired DecimalFormatSymbols | 860 * @return desired DecimalFormatSymbols |
(...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2085 * possible. For strings corresponding to return values of Infinity, -Infinity
, NaN, and -0.0, a | 2110 * possible. For strings corresponding to return values of Infinity, -Infinity
, NaN, and -0.0, a |
2086 * Double will be returned even if ParseBigDecimal is enabled. | 2111 * Double will be returned even if ParseBigDecimal is enabled. |
2087 * | 2112 * |
2088 * @param value true to cause {@link #parse} to prefer BigDecimal; false to le
t {@link #parse} | 2113 * @param value true to cause {@link #parse} to prefer BigDecimal; false to le
t {@link #parse} |
2089 * return additional data types like Long or BigInteger. | 2114 * return additional data types like Long or BigInteger. |
2090 * @category Parsing | 2115 * @category Parsing |
2091 * @stable ICU 3.6 | 2116 * @stable ICU 3.6 |
2092 */ | 2117 */ |
2093 public synchronized void setParseBigDecimal(boolean value) { | 2118 public synchronized void setParseBigDecimal(boolean value) { |
2094 properties.setParseToBigDecimal(value); | 2119 properties.setParseToBigDecimal(value); |
2095 // refreshFormatter() not needed | 2120 refreshFormatter(); |
2096 } | 2121 } |
2097 | 2122 |
2098 /** | 2123 /** |
2099 * Always returns 1000, the default prior to ICU 59. | 2124 * Always returns 1000, the default prior to ICU 59. |
2100 * | 2125 * |
2101 * @category Parsing | 2126 * @category Parsing |
2102 * @deprecated Setting max parse digits has no effect since ICU4J 59. | 2127 * @deprecated Setting max parse digits has no effect since ICU4J 59. |
2103 */ | 2128 */ |
2104 @Deprecated | 2129 @Deprecated |
2105 public int getParseMaxDigits() { | 2130 public int getParseMaxDigits() { |
(...skipping 23 matching lines...) Expand all Loading... |
2129 /** | 2154 /** |
2130 * {@inheritDoc} | 2155 * {@inheritDoc} |
2131 * | 2156 * |
2132 * @category Parsing | 2157 * @category Parsing |
2133 * @stable ICU 3.6 | 2158 * @stable ICU 3.6 |
2134 */ | 2159 */ |
2135 @Override | 2160 @Override |
2136 public synchronized void setParseStrict(boolean parseStrict) { | 2161 public synchronized void setParseStrict(boolean parseStrict) { |
2137 Parse.ParseMode mode = parseStrict ? Parse.ParseMode.STRICT : Parse.ParseMod
e.LENIENT; | 2162 Parse.ParseMode mode = parseStrict ? Parse.ParseMode.STRICT : Parse.ParseMod
e.LENIENT; |
2138 properties.setParseMode(mode); | 2163 properties.setParseMode(mode); |
2139 // refreshFormatter() not needed | 2164 refreshFormatter(); |
2140 } | 2165 } |
2141 | 2166 |
2142 /** | 2167 /** |
2143 * {@inheritDoc} | 2168 * {@inheritDoc} |
2144 * | 2169 * |
2145 * @see #setParseIntegerOnly | 2170 * @see #setParseIntegerOnly |
2146 * @category Parsing | 2171 * @category Parsing |
2147 * @stable ICU 2.0 | 2172 * @stable ICU 2.0 |
2148 */ | 2173 */ |
2149 @Override | 2174 @Override |
2150 public synchronized boolean isParseIntegerOnly() { | 2175 public synchronized boolean isParseIntegerOnly() { |
2151 return properties.getParseIntegerOnly(); | 2176 return properties.getParseIntegerOnly(); |
2152 } | 2177 } |
2153 | 2178 |
2154 /** | 2179 /** |
2155 * <strong>Parsing:</strong> {@inheritDoc} | 2180 * <strong>Parsing:</strong> {@inheritDoc} |
2156 * | 2181 * |
2157 * <p>This is functionally equivalent to calling {@link #setDecimalPatternMatc
hRequired} and a | 2182 * <p>This is functionally equivalent to calling {@link #setDecimalPatternMatc
hRequired} and a |
2158 * pattern without a decimal point. | 2183 * pattern without a decimal point. |
2159 * | 2184 * |
2160 * @param parseIntegerOnly true to ignore fractional parts of numbers when par
sing; false to | 2185 * @param parseIntegerOnly true to ignore fractional parts of numbers when par
sing; false to |
2161 * consume fractional parts. | 2186 * consume fractional parts. |
2162 * @category Parsing | 2187 * @category Parsing |
2163 * @stable ICU 2.0 | 2188 * @stable ICU 2.0 |
2164 */ | 2189 */ |
2165 @Override | 2190 @Override |
2166 public synchronized void setParseIntegerOnly(boolean parseIntegerOnly) { | 2191 public synchronized void setParseIntegerOnly(boolean parseIntegerOnly) { |
2167 properties.setParseIntegerOnly(parseIntegerOnly); | 2192 properties.setParseIntegerOnly(parseIntegerOnly); |
2168 // refreshFormatter() not needed | 2193 refreshFormatter(); |
2169 } | 2194 } |
2170 | 2195 |
2171 /** | 2196 /** |
2172 * {@icu} Returns whether the presence of a decimal point must match the patte
rn. | 2197 * {@icu} Returns whether the presence of a decimal point must match the patte
rn. |
2173 * | 2198 * |
2174 * @see #setDecimalPatternMatchRequired | 2199 * @see #setDecimalPatternMatchRequired |
2175 * @category Parsing | 2200 * @category Parsing |
2176 * @stable ICU 54 | 2201 * @stable ICU 54 |
2177 */ | 2202 */ |
2178 public synchronized boolean isDecimalPatternMatchRequired() { | 2203 public synchronized boolean isDecimalPatternMatchRequired() { |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2452 if (locale == null) { | 2477 if (locale == null) { |
2453 // Constructor | 2478 // Constructor |
2454 locale = symbols.getLocale(ULocale.ACTUAL_LOCALE); | 2479 locale = symbols.getLocale(ULocale.ACTUAL_LOCALE); |
2455 } | 2480 } |
2456 if (locale == null) { | 2481 if (locale == null) { |
2457 // Deserialization | 2482 // Deserialization |
2458 locale = symbols.getULocale(); | 2483 locale = symbols.getULocale(); |
2459 } | 2484 } |
2460 assert locale != null; | 2485 assert locale != null; |
2461 formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedP
roperties).locale(locale); | 2486 formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedP
roperties).locale(locale); |
| 2487 parser = NumberParserImpl.createParserFromProperties(properties, symbols, fa
lse, false); |
| 2488 parserWithCurrency = NumberParserImpl.createParserFromProperties(properties,
symbols, true, false); |
2462 } | 2489 } |
2463 | 2490 |
2464 /** | 2491 /** |
2465 * Converts a java.math.BigDecimal to a com.ibm.icu.math.BigDecimal with fallb
ack for numbers | 2492 * Converts a java.math.BigDecimal to a com.ibm.icu.math.BigDecimal with fallb
ack for numbers |
2466 * outside of the range supported by com.ibm.icu.math.BigDecimal. | 2493 * outside of the range supported by com.ibm.icu.math.BigDecimal. |
2467 * | 2494 * |
2468 * @param number | 2495 * @param number |
2469 * @return | 2496 * @return |
2470 */ | 2497 */ |
2471 private Number safeConvertBigDecimal(java.math.BigDecimal number) { | 2498 private Number safeConvertBigDecimal(java.math.BigDecimal number) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2585 * | 2612 * |
2586 * @see #setPadPosition | 2613 * @see #setPadPosition |
2587 * @see #getPadPosition | 2614 * @see #getPadPosition |
2588 * @see #PAD_BEFORE_PREFIX | 2615 * @see #PAD_BEFORE_PREFIX |
2589 * @see #PAD_AFTER_PREFIX | 2616 * @see #PAD_AFTER_PREFIX |
2590 * @see #PAD_BEFORE_SUFFIX | 2617 * @see #PAD_BEFORE_SUFFIX |
2591 * @stable ICU 2.0 | 2618 * @stable ICU 2.0 |
2592 */ | 2619 */ |
2593 public static final int PAD_AFTER_SUFFIX = 3; | 2620 public static final int PAD_AFTER_SUFFIX = 3; |
2594 } | 2621 } |
OLD | NEW |