LEFT | RIGHT |
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.impl.number; | 3 package com.ibm.icu.impl.number; |
4 | 4 |
5 import java.math.BigDecimal; | 5 import java.math.BigDecimal; |
6 import java.math.MathContext; | 6 import java.math.MathContext; |
7 import java.text.ParseException; | 7 import java.text.ParseException; |
8 import java.text.ParsePosition; | 8 import java.text.ParsePosition; |
9 import java.util.HashSet; | 9 import java.util.HashSet; |
10 import java.util.Iterator; | 10 import java.util.Iterator; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 /** | 112 /** |
113 * Whether to ignore the fractional part of numbers. For example, parses "12
3.4" to "123" | 113 * Whether to ignore the fractional part of numbers. For example, parses "12
3.4" to "123" |
114 * instead of "123.4". | 114 * instead of "123.4". |
115 * | 115 * |
116 * @param parseIntegerOnly true to parse integers only; false to parse integ
ers with their | 116 * @param parseIntegerOnly true to parse integers only; false to parse integ
ers with their |
117 * fraction parts | 117 * fraction parts |
118 * @return The property bag, for chaining. | 118 * @return The property bag, for chaining. |
119 */ | 119 */ |
120 public IProperties setParseIntegerOnly(boolean parseIntegerOnly); | 120 public IProperties setParseIntegerOnly(boolean parseIntegerOnly); |
121 | 121 |
122 boolean DEFAULT_PARSE_IGNORE_EXPONENT = false; | 122 boolean DEFAULT_PARSE_NO_EXPONENT = false; |
123 | 123 |
124 /** @see #setParseIgnoreExponent */ | 124 /** @see #setParseNoExponent */ |
125 public boolean getParseIgnoreExponent(); | 125 public boolean getParseNoExponent(); |
126 | 126 |
127 /** | 127 /** |
128 * Whether to ignore the exponential part of numbers. For example, parses "1
23E4" to "123" | 128 * Whether to ignore the exponential part of numbers. For example, parses "1
23E4" to "123" |
129 * instead of "1230000". | 129 * instead of "1230000". |
130 * | 130 * |
131 * @param parseIgnoreExponent true to ignore exponents; false to parse them. | 131 * @param parseIgnoreExponent true to ignore exponents; false to parse them. |
132 * @return The property bag, for chaining. | 132 * @return The property bag, for chaining. |
133 */ | 133 */ |
134 public IProperties setParseIgnoreExponent(boolean parseIgnoreExponent); | 134 public IProperties setParseNoExponent(boolean parseIgnoreExponent); |
135 | 135 |
136 boolean DEFAULT_DECIMAL_PATTERN_MATCH_REQUIRED = false; | 136 boolean DEFAULT_DECIMAL_PATTERN_MATCH_REQUIRED = false; |
137 | 137 |
138 /** @see #setDecimalPatternMatchRequired */ | 138 /** @see #setDecimalPatternMatchRequired */ |
139 public boolean getDecimalPatternMatchRequired(); | 139 public boolean getDecimalPatternMatchRequired(); |
140 | 140 |
141 /** | 141 /** |
142 * Whether to require that a decimal point be present. If a decimal point is
not present, the | 142 * Whether to require that the presence of decimal point matches the pattern
. If a decimal point |
143 * parse will not succeed: null will be returned from <code>parse()</code>,
and an error index | 143 * is not present, but the pattern contained a decimal point, parse will not
succeed: null will |
144 * will be set in the {@link ParsePosition}. | 144 * be returned from <code>parse()</code>, and an error index will be set in
the {@link |
| 145 * ParsePosition}. |
145 * | 146 * |
146 * @param decimalPatternMatchRequired true to set an error if decimal is not
present | 147 * @param decimalPatternMatchRequired true to set an error if decimal is not
present |
147 * @return The property bag, for chaining. | 148 * @return The property bag, for chaining. |
148 */ | 149 */ |
149 public IProperties setDecimalPatternMatchRequired(boolean decimalPatternMatc
hRequired); | 150 public IProperties setDecimalPatternMatchRequired(boolean decimalPatternMatc
hRequired); |
150 | 151 |
151 ParseMode DEFAULT_PARSE_MODE = ParseMode.LENIENT; | 152 ParseMode DEFAULT_PARSE_MODE = null; |
152 | 153 |
153 /** @see #setParseMode */ | 154 /** @see #setParseMode */ |
154 public ParseMode getParseMode(); | 155 public ParseMode getParseMode(); |
155 | 156 |
156 /** | 157 /** |
157 * Controls certain rules for how strict this parser is when reading strings
. See {@link | 158 * Controls certain rules for how strict this parser is when reading strings
. See {@link |
158 * ParseMode#LENIENT} and {@link ParseMode#STRICT}. | 159 * ParseMode#LENIENT} and {@link ParseMode#STRICT}. |
159 * | 160 * |
160 * @param parseMode Either {@link ParseMode#LENIENT} or {@link ParseMode#STR
ICT}. | 161 * @param parseMode Either {@link ParseMode#LENIENT} or {@link ParseMode#STR
ICT}. |
161 * @return The property bag, for chaining. | 162 * @return The property bag, for chaining. |
162 */ | 163 */ |
163 public IProperties setParseMode(ParseMode parseMode); | 164 public IProperties setParseMode(ParseMode parseMode); |
164 | |
165 // boolean DEFAULT_PARSE_CURRENCY = false; | |
166 // | |
167 // /** @see #setParseCurrency */ | |
168 // public boolean getParseCurrency(); | |
169 // | |
170 // /** | |
171 // * Whether to parse currency codes and currency names in the string. | |
172 // * | |
173 // * <p>Due to the large number of possible currencies, enabling this op
tion may impact the | |
174 // * runtime of the parse operation. | |
175 // * | |
176 // * @param parseCurrency true to parse arbitrary currency codes and cur
rency names; false to | |
177 // * disable. (Default is false) | |
178 // * @return The property bag, for chaining. | |
179 // */ | |
180 // public IProperties setParseCurrency(boolean parseCurrency); | |
181 | 165 |
182 boolean DEFAULT_PARSE_TO_BIG_DECIMAL = false; | 166 boolean DEFAULT_PARSE_TO_BIG_DECIMAL = false; |
183 | 167 |
184 /** @see #setParseToBigDecimal */ | 168 /** @see #setParseToBigDecimal */ |
185 public boolean getParseToBigDecimal(); | 169 public boolean getParseToBigDecimal(); |
186 | 170 |
187 /** | 171 /** |
188 * Whether to always return a BigDecimal from {@link Parse#parse} and all ot
her parse methods. | 172 * Whether to always return a BigDecimal from {@link Parse#parse} and all ot
her parse methods. |
189 * By default, a Long or a BigInteger are returned when possible. | 173 * By default, a Long or a BigInteger are returned when possible. |
190 * | 174 * |
(...skipping 14 matching lines...) Expand all Loading... |
205 * symbol. Grouping separators, decimal separators, and padding are always c
ase-sensitive. | 189 * symbol. Grouping separators, decimal separators, and padding are always c
ase-sensitive. |
206 * Currencies are always case-insensitive. | 190 * Currencies are always case-insensitive. |
207 * | 191 * |
208 * <p>This setting is ignored in fast mode. In fast mode, strings are always
compared in a | 192 * <p>This setting is ignored in fast mode. In fast mode, strings are always
compared in a |
209 * case-sensitive way. | 193 * case-sensitive way. |
210 * | 194 * |
211 * @param parseCaseSensitive true to be case-sensitive when parsing; false t
o allow any case. | 195 * @param parseCaseSensitive true to be case-sensitive when parsing; false t
o allow any case. |
212 * @return The property bag, for chaining. | 196 * @return The property bag, for chaining. |
213 */ | 197 */ |
214 public IProperties setParseCaseSensitive(boolean parseCaseSensitive); | 198 public IProperties setParseCaseSensitive(boolean parseCaseSensitive); |
215 | |
216 // boolean DEFAULT_PARSE_STRICT = false; | |
217 // | |
218 // /** @see #setParseStrict */ | |
219 // public boolean getParseStrict(); | |
220 // | |
221 // public IProperties setParseStrict(boolean parseStrict); | |
222 // | |
223 // boolean DEFAULT_PARSE_FAST = true; | |
224 // | |
225 // /** @see #setParseFastMode */ | |
226 // public boolean getParseFastMode(); | |
227 // | |
228 // public IProperties setParseFastMode(boolean parseFastMode); | |
229 } | 199 } |
230 | 200 |
231 /** | 201 /** |
232 * @see #parse(String, ParsePosition, ParseMode, boolean, boolean, IProperties
, | 202 * @see #parse(String, ParsePosition, ParseMode, boolean, boolean, IProperties
, |
233 * DecimalFormatSymbols) | 203 * DecimalFormatSymbols) |
234 */ | 204 */ |
235 private static enum StateName { | 205 private static enum StateName { |
236 BEFORE_PREFIX, | 206 BEFORE_PREFIX, |
237 AFTER_PREFIX, | 207 AFTER_PREFIX, |
238 AFTER_INTEGER_DIGIT, | 208 AFTER_INTEGER_DIGIT, |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 // Other pre-computed fields: | 602 // Other pre-computed fields: |
633 int decimalCp1; | 603 int decimalCp1; |
634 int decimalCp2; | 604 int decimalCp2; |
635 int groupingCp1; | 605 int groupingCp1; |
636 int groupingCp2; | 606 int groupingCp2; |
637 SeparatorType decimalType1; | 607 SeparatorType decimalType1; |
638 SeparatorType decimalType2; | 608 SeparatorType decimalType2; |
639 SeparatorType groupingType1; | 609 SeparatorType groupingType1; |
640 SeparatorType groupingType2; | 610 SeparatorType groupingType2; |
641 TextTrieMap<Byte> digitTrie; | 611 TextTrieMap<Byte> digitTrie; |
642 Set<AffixHolder> affixHolders = new HashSet<>(); | 612 Set<AffixHolder> affixHolders = new HashSet<AffixHolder>(); |
643 | 613 |
644 ParserState() { | 614 ParserState() { |
645 for (int i = 0; i < items.length; i++) { | 615 for (int i = 0; i < items.length; i++) { |
646 items[i] = new StateItem(); | 616 items[i] = new StateItem(); |
647 prevItems[i] = new StateItem(); | 617 prevItems[i] = new StateItem(); |
648 } | 618 } |
649 } | 619 } |
650 | 620 |
651 /** | 621 /** |
652 * Clears the internal state in order to prepare for parsing a new string. | 622 * Clears the internal state in order to prepare for parsing a new string. |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 static final AffixHolder EMPTY_NEGATIVE = new AffixHolder("", "", true, true
); | 706 static final AffixHolder EMPTY_NEGATIVE = new AffixHolder("", "", true, true
); |
737 static final AffixHolder DEFAULT_POSITIVE = new AffixHolder("+", "", false,
false); | 707 static final AffixHolder DEFAULT_POSITIVE = new AffixHolder("+", "", false,
false); |
738 static final AffixHolder DEFAULT_NEGATIVE = new AffixHolder("-", "", false,
true); | 708 static final AffixHolder DEFAULT_NEGATIVE = new AffixHolder("-", "", false,
true); |
739 | 709 |
740 static void addToState(ParserState state, IProperties properties) { | 710 static void addToState(ParserState state, IProperties properties) { |
741 AffixHolder pp = fromPropertiesPositivePattern(properties); | 711 AffixHolder pp = fromPropertiesPositivePattern(properties); |
742 AffixHolder np = fromPropertiesNegativePattern(properties); | 712 AffixHolder np = fromPropertiesNegativePattern(properties); |
743 AffixHolder ps = fromPropertiesPositiveString(properties); | 713 AffixHolder ps = fromPropertiesPositiveString(properties); |
744 AffixHolder ns = fromPropertiesNegativeString(properties); | 714 AffixHolder ns = fromPropertiesNegativeString(properties); |
745 if (pp == null && ps == null) { | 715 if (pp == null && ps == null) { |
746 if (properties.getAlwaysShowPlusSign()) { | 716 if (properties.getPlusSignAlwaysShown()) { |
747 state.affixHolders.add(DEFAULT_POSITIVE); | 717 state.affixHolders.add(DEFAULT_POSITIVE); |
748 } else { | 718 } else { |
749 state.affixHolders.add(EMPTY_POSITIVE); | 719 state.affixHolders.add(EMPTY_POSITIVE); |
750 } | 720 } |
751 } else { | 721 } else { |
752 if (pp != null) state.affixHolders.add(pp); | 722 if (pp != null) state.affixHolders.add(pp); |
753 if (ps != null) state.affixHolders.add(ps); | 723 if (ps != null) state.affixHolders.add(ps); |
754 } | 724 } |
755 if (np == null && ns == null) { | 725 if (np == null && ns == null) { |
756 state.affixHolders.add(DEFAULT_NEGATIVE); | 726 state.affixHolders.add(DEFAULT_NEGATIVE); |
757 } else { | 727 } else { |
758 if (np != null) state.affixHolders.add(np); | 728 if (np != null) state.affixHolders.add(np); |
759 if (ns != null) state.affixHolders.add(ns); | 729 if (ns != null) state.affixHolders.add(ns); |
760 } | 730 } |
761 } | 731 } |
762 | 732 |
763 static AffixHolder fromPropertiesPositivePattern(IProperties properties) { | 733 static AffixHolder fromPropertiesPositivePattern(IProperties properties) { |
764 CharSequence ppp = properties.getPositivePrefixPattern(); | 734 String ppp = properties.getPositivePrefixPattern(); |
765 CharSequence psp = properties.getPositiveSuffixPattern(); | 735 String psp = properties.getPositiveSuffixPattern(); |
766 return getInstance(ppp, psp, false, false); | 736 return getInstance(ppp, psp, false, false); |
767 } | 737 } |
768 | 738 |
769 static AffixHolder fromPropertiesNegativePattern(IProperties properties) { | 739 static AffixHolder fromPropertiesNegativePattern(IProperties properties) { |
770 CharSequence npp = properties.getNegativePrefixPattern(); | 740 String npp = properties.getNegativePrefixPattern(); |
771 CharSequence nsp = properties.getNegativeSuffixPattern(); | 741 String nsp = properties.getNegativeSuffixPattern(); |
772 return getInstance(npp, nsp, false, true); | 742 return getInstance(npp, nsp, false, true); |
773 } | 743 } |
774 | 744 |
775 static AffixHolder fromPropertiesPositiveString(IProperties properties) { | 745 static AffixHolder fromPropertiesPositiveString(IProperties properties) { |
776 CharSequence pp = properties.getPositivePrefix(); | 746 String pp = properties.getPositivePrefix(); |
777 CharSequence ps = properties.getPositiveSuffix(); | 747 String ps = properties.getPositiveSuffix(); |
778 return getInstance(pp, ps, true, false); | 748 return getInstance(pp, ps, true, false); |
779 } | 749 } |
780 | 750 |
781 static AffixHolder fromPropertiesNegativeString(IProperties properties) { | 751 static AffixHolder fromPropertiesNegativeString(IProperties properties) { |
782 CharSequence np = properties.getNegativePrefix(); | 752 String np = properties.getNegativePrefix(); |
783 CharSequence ns = properties.getNegativeSuffix(); | 753 String ns = properties.getNegativeSuffix(); |
784 return getInstance(np, ns, true, true); | 754 return getInstance(np, ns, true, true); |
785 } | 755 } |
786 | 756 |
787 static AffixHolder getInstance( | 757 static AffixHolder getInstance(String p, String s, boolean strings, boolean
negative) { |
788 CharSequence p, CharSequence s, boolean strings, boolean negative) { | |
789 if (p == null && s == null) return null; | 758 if (p == null && s == null) return null; |
790 if (p == null) p = ""; | 759 if (p == null) p = ""; |
791 if (s == null) s = ""; | 760 if (s == null) s = ""; |
792 if (p.length() == 0 && s.length() == 0) return negative ? EMPTY_NEGATIVE :
EMPTY_POSITIVE; | 761 if (p.length() == 0 && s.length() == 0) return negative ? EMPTY_NEGATIVE :
EMPTY_POSITIVE; |
793 return new AffixHolder(p.toString(), s.toString(), strings, negative); | 762 return new AffixHolder(p, s, strings, negative); |
794 } | 763 } |
795 | 764 |
796 AffixHolder(String pp, String sp, boolean strings, boolean negative) { | 765 AffixHolder(String pp, String sp, boolean strings, boolean negative) { |
797 this.p = pp; | 766 this.p = pp; |
798 this.s = sp; | 767 this.s = sp; |
799 this.strings = strings; | 768 this.strings = strings; |
800 this.negative = negative; | 769 this.negative = negative; |
801 } | 770 } |
802 | 771 |
803 @Override | 772 @Override |
(...skipping 26 matching lines...) Expand all Loading... |
830 sb.append("}"); | 799 sb.append("}"); |
831 return sb.toString(); | 800 return sb.toString(); |
832 } | 801 } |
833 } | 802 } |
834 | 803 |
835 /** | 804 /** |
836 * A class that holds information about all currency affix patterns for the lo
cale. This allows | 805 * A class that holds information about all currency affix patterns for the lo
cale. This allows |
837 * the parser to accept currencies in any format that are valid for the locale
. | 806 * the parser to accept currencies in any format that are valid for the locale
. |
838 */ | 807 */ |
839 private static class CurrencyAffixPatterns { | 808 private static class CurrencyAffixPatterns { |
840 private final Set<AffixHolder> set = new HashSet<>(); | 809 private final Set<AffixHolder> set = new HashSet<AffixHolder>(); |
841 | 810 |
842 private static final ConcurrentHashMap<ULocale, CurrencyAffixPatterns> curre
ncyAffixPatterns = | 811 private static final ConcurrentHashMap<ULocale, CurrencyAffixPatterns> curre
ncyAffixPatterns = |
843 new ConcurrentHashMap<>(); | 812 new ConcurrentHashMap<ULocale, CurrencyAffixPatterns>(); |
844 | 813 |
845 static void addToState(ULocale uloc, ParserState state) { | 814 static void addToState(ULocale uloc, ParserState state) { |
846 if (!currencyAffixPatterns.contains(uloc)) { | 815 if (!currencyAffixPatterns.containsKey(uloc)) { |
847 // There can be multiple threads computing the same CurrencyAffixPattern
s simultaneously, | 816 // There can be multiple threads computing the same CurrencyAffixPattern
s simultaneously, |
848 // but that scenario is harmless. | 817 // but that scenario is harmless. |
849 CurrencyAffixPatterns value = new CurrencyAffixPatterns(uloc); | 818 CurrencyAffixPatterns value = new CurrencyAffixPatterns(uloc); |
850 currencyAffixPatterns.put(uloc, value); | 819 currencyAffixPatterns.put(uloc, value); |
851 } | 820 } |
852 CurrencyAffixPatterns instance = currencyAffixPatterns.get(uloc); | 821 CurrencyAffixPatterns instance = currencyAffixPatterns.get(uloc); |
853 state.affixHolders.addAll(instance.set); | 822 state.affixHolders.addAll(instance.set); |
854 } | 823 } |
855 | 824 |
856 private CurrencyAffixPatterns(ULocale uloc) { | 825 private CurrencyAffixPatterns(ULocale uloc) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 boolean requiresTrie = false; | 868 boolean requiresTrie = false; |
900 for (int i = 0; i < 10; i++) { | 869 for (int i = 0; i < 10; i++) { |
901 String str = digitStrings[i]; | 870 String str = digitStrings[i]; |
902 if (Character.charCount(Character.codePointAt(str, 0)) != str.length()) { | 871 if (Character.charCount(Character.codePointAt(str, 0)) != str.length()) { |
903 requiresTrie = true; | 872 requiresTrie = true; |
904 break; | 873 break; |
905 } | 874 } |
906 } | 875 } |
907 if (!requiresTrie) return null; | 876 if (!requiresTrie) return null; |
908 | 877 |
909 TextTrieMap<Byte> trieMap = new TextTrieMap<>(false); | 878 TextTrieMap<Byte> trieMap = new TextTrieMap<Byte>(false); |
910 for (int i = 0; i < 10; i++) { | 879 for (int i = 0; i < 10; i++) { |
911 trieMap.put(digitStrings[i], (byte) i); | 880 trieMap.put(digitStrings[i], (byte) i); |
912 } | 881 } |
913 return trieMap; | 882 return trieMap; |
914 } | 883 } |
915 | 884 |
916 protected static final ThreadLocal<ParserState> threadLocalParseState = | 885 protected static final ThreadLocal<ParserState> threadLocalParseState = |
917 new ThreadLocal<ParserState>() { | 886 new ThreadLocal<ParserState>() { |
918 @Override | 887 @Override |
919 protected ParserState initialValue() { | 888 protected ParserState initialValue() { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 ParsePosition ppos, | 976 ParsePosition ppos, |
1008 boolean parseCurrency, | 977 boolean parseCurrency, |
1009 IProperties properties, | 978 IProperties properties, |
1010 DecimalFormatSymbols symbols) { | 979 DecimalFormatSymbols symbols) { |
1011 | 980 |
1012 if (input == null || ppos == null || properties == null || symbols == null)
{ | 981 if (input == null || ppos == null || properties == null || symbols == null)
{ |
1013 throw new IllegalArgumentException("All arguments are required for parse."
); | 982 throw new IllegalArgumentException("All arguments are required for parse."
); |
1014 } | 983 } |
1015 | 984 |
1016 ParseMode mode = properties.getParseMode(); | 985 ParseMode mode = properties.getParseMode(); |
| 986 if (mode == null) mode = ParseMode.LENIENT; |
1017 boolean integerOnly = properties.getParseIntegerOnly(); | 987 boolean integerOnly = properties.getParseIntegerOnly(); |
1018 boolean ignoreExponent = properties.getParseIgnoreExponent(); | 988 boolean ignoreExponent = properties.getParseNoExponent(); |
1019 | 989 |
1020 // Set up the initial state | 990 // Set up the initial state |
1021 ParserState state = threadLocalParseState.get().clear(); | 991 ParserState state = threadLocalParseState.get().clear(); |
1022 state.properties = properties; | 992 state.properties = properties; |
1023 state.symbols = symbols; | 993 state.symbols = symbols; |
1024 state.mode = mode; | 994 state.mode = mode; |
1025 state.parseCurrency = parseCurrency; | 995 state.parseCurrency = parseCurrency; |
1026 state.caseSensitive = properties.getParseCaseSensitive(); | 996 state.caseSensitive = properties.getParseCaseSensitive(); |
1027 state.decimalCp1 = Character.codePointAt(symbols.getDecimalSeparatorString()
, 0); | 997 state.decimalCp1 = Character.codePointAt(symbols.getDecimalSeparatorString()
, 0); |
1028 state.decimalCp2 = Character.codePointAt(symbols.getMonetaryDecimalSeparator
String(), 0); | 998 state.decimalCp2 = Character.codePointAt(symbols.getMonetaryDecimalSeparator
String(), 0); |
1029 state.groupingCp1 = Character.codePointAt(symbols.getGroupingSeparatorString
(), 0); | 999 state.groupingCp1 = Character.codePointAt(symbols.getGroupingSeparatorString
(), 0); |
1030 state.groupingCp2 = Character.codePointAt(symbols.getMonetaryGroupingSeparat
orString(), 0); | 1000 state.groupingCp2 = Character.codePointAt(symbols.getMonetaryGroupingSeparat
orString(), 0); |
1031 state.decimalType1 = SeparatorType.fromCp(state.decimalCp1, mode); | 1001 state.decimalType1 = SeparatorType.fromCp(state.decimalCp1, mode); |
1032 state.decimalType2 = SeparatorType.fromCp(state.decimalCp1, mode); | 1002 state.decimalType2 = SeparatorType.fromCp(state.decimalCp2, mode); |
1033 state.groupingType1 = SeparatorType.fromCp(state.groupingCp1, mode); | 1003 state.groupingType1 = SeparatorType.fromCp(state.groupingCp1, mode); |
1034 state.groupingType2 = SeparatorType.fromCp(state.groupingCp1, mode); | 1004 state.groupingType2 = SeparatorType.fromCp(state.groupingCp2, mode); |
1035 StateItem initialStateItem = state.getNext().clear(); | 1005 StateItem initialStateItem = state.getNext().clear(); |
1036 initialStateItem.name = StateName.BEFORE_PREFIX; | 1006 initialStateItem.name = StateName.BEFORE_PREFIX; |
1037 | 1007 |
1038 if (mode == ParseMode.LENIENT || mode == ParseMode.STRICT) { | 1008 if (mode == ParseMode.LENIENT || mode == ParseMode.STRICT) { |
1039 state.digitTrie = makeDigitTrie(symbols.getDigitStringsLocal()); | 1009 state.digitTrie = makeDigitTrie(symbols.getDigitStringsLocal()); |
1040 AffixHolder.addToState(state, properties); | 1010 AffixHolder.addToState(state, properties); |
1041 if (parseCurrency) { | 1011 if (parseCurrency) { |
1042 CurrencyAffixPatterns.addToState(symbols.getULocale(), state); | 1012 CurrencyAffixPatterns.addToState(symbols.getULocale(), state); |
1043 } | 1013 } |
1044 } | 1014 } |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 for (int j = 1; j < numGroupingRegions - 1; j++) { | 1333 for (int j = 1; j < numGroupingRegions - 1; j++) { |
1364 if (((groupingWidths >>> (j * 4)) & 0xf) != grouping2) { | 1334 if (((groupingWidths >>> (j * 4)) & 0xf) != grouping2) { |
1365 // A grouping size somewhere in the middle is invalid | 1335 // A grouping size somewhere in the middle is invalid |
1366 if (DEBUGGING) System.out.println("-> rejected due to inner grou
ping violation"); | 1336 if (DEBUGGING) System.out.println("-> rejected due to inner grou
ping violation"); |
1367 continue outer; | 1337 continue outer; |
1368 } | 1338 } |
1369 } | 1339 } |
1370 } | 1340 } |
1371 } | 1341 } |
1372 | 1342 |
1373 // Optionally require that a decimal point be present. | 1343 // Optionally require that the presence of a decimal point matches the p
attern. |
1374 if (properties.getDecimalPatternMatchRequired() && !item.sawDecimalPoint
) { | 1344 if (properties.getDecimalPatternMatchRequired() |
| 1345 && item.sawDecimalPoint != PositiveDecimalFormat.allowsDecimalPoint(
properties)) { |
1375 if (DEBUGGING) System.out.println("-> rejected due to decimal point vi
olation"); | 1346 if (DEBUGGING) System.out.println("-> rejected due to decimal point vi
olation"); |
1376 continue; | 1347 continue; |
1377 } | 1348 } |
1378 | 1349 |
1379 // When parsing currencies, require that a currency symbol was found. | 1350 // When parsing currencies, require that a currency symbol was found. |
1380 if (parseCurrency && !item.sawCurrency) { | 1351 if (parseCurrency && !item.sawCurrency) { |
1381 if (DEBUGGING) System.out.println("-> rejected due to lack of currency
"); | 1352 if (DEBUGGING) System.out.println("-> rejected due to lack of currency
"); |
1382 continue; | 1353 continue; |
1383 } | 1354 } |
1384 | 1355 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1442 * If <code>cp</code> is a padding character (as determined by {@link ParserSt
ate#paddingCp}), | 1413 * If <code>cp</code> is a padding character (as determined by {@link ParserSt
ate#paddingCp}), |
1443 * copies <code>item</code> to the new list in <code>state</code> and sets its
state name to | 1414 * copies <code>item</code> to the new list in <code>state</code> and sets its
state name to |
1444 * <code>nextName</code>. | 1415 * <code>nextName</code>. |
1445 * | 1416 * |
1446 * @param cp The code point to check. | 1417 * @param cp The code point to check. |
1447 * @param nextName The new state name if the check passes. | 1418 * @param nextName The new state name if the check passes. |
1448 * @param state The state object to update. | 1419 * @param state The state object to update. |
1449 * @param item The old state leading into the code point. | 1420 * @param item The old state leading into the code point. |
1450 */ | 1421 */ |
1451 private static void acceptPadding(int cp, StateName nextName, ParserState stat
e, StateItem item) { | 1422 private static void acceptPadding(int cp, StateName nextName, ParserState stat
e, StateItem item) { |
1452 CharSequence padding = state.properties.getPaddingString(); | 1423 CharSequence padding = state.properties.getPadString(); |
1453 if (padding == null || padding.length() == 0) return; | 1424 if (padding == null || padding.length() == 0) return; |
1454 int referenceCp = Character.codePointAt(padding, 0); | 1425 int referenceCp = Character.codePointAt(padding, 0); |
1455 if (cp == referenceCp) { | 1426 if (cp == referenceCp) { |
1456 state.getNext().copyFrom(item, nextName, cp); | 1427 state.getNext().copyFrom(item, nextName, cp); |
1457 } | 1428 } |
1458 } | 1429 } |
1459 | 1430 |
1460 private static void acceptIntegerDigit( | 1431 private static void acceptIntegerDigit( |
1461 int cp, StateName nextName, ParserState state, StateItem item) { | 1432 int cp, StateName nextName, ParserState state, StateItem item) { |
1462 acceptDigitHelper(cp, nextName, state, item, DigitType.INTEGER); | 1433 acceptDigitHelper(cp, nextName, state, item, DigitType.INTEGER); |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1624 */ | 1595 */ |
1625 private static void acceptDecimalPoint( | 1596 private static void acceptDecimalPoint( |
1626 int cp, StateName nextName, ParserState state, StateItem item) { | 1597 int cp, StateName nextName, ParserState state, StateItem item) { |
1627 if (cp == item.groupingCp) { | 1598 if (cp == item.groupingCp) { |
1628 // Don't accept a decimal point that is the same as the grouping separator | 1599 // Don't accept a decimal point that is the same as the grouping separator |
1629 return; | 1600 return; |
1630 } | 1601 } |
1631 | 1602 |
1632 SeparatorType cpType = SeparatorType.fromCp(cp, state.mode); | 1603 SeparatorType cpType = SeparatorType.fromCp(cp, state.mode); |
1633 | 1604 |
1634 // Always accept if exactly the same as the locale symbol. | 1605 // We require that the decimal separator be in the same class as the locale. |
1635 // Otherwise, reject if UNKNOWN, OTHER, the same class as the decimal separa
tor. | 1606 if (cpType != state.decimalType1 && cpType != state.decimalType2) { |
1636 if (cp != state.decimalCp1 && cp != state.decimalCp2) { | 1607 return; |
1637 if (cpType == SeparatorType.UNKNOWN || cpType == SeparatorType.OTHER_GROUP
ING) { | 1608 } |
1638 return; | 1609 |
1639 } | 1610 // If in UNKNOWN or OTHER, require an exact match. |
1640 if (cpType == SeparatorType.COMMA_LIKE | 1611 if (cpType == SeparatorType.OTHER_GROUPING || cpType == SeparatorType.UNKNOW
N) { |
1641 && (state.groupingType1 == SeparatorType.COMMA_LIKE | 1612 if (cp != state.decimalCp1 && cp != state.decimalCp2) { |
1642 || state.groupingType2 == SeparatorType.COMMA_LIKE)) { | |
1643 return; | |
1644 } | |
1645 if (cpType == SeparatorType.PERIOD_LIKE | |
1646 && (state.groupingType1 == SeparatorType.PERIOD_LIKE | |
1647 || state.groupingType2 == SeparatorType.PERIOD_LIKE)) { | |
1648 return; | 1613 return; |
1649 } | 1614 } |
1650 } | 1615 } |
1651 | 1616 |
1652 // A match was found. | 1617 // A match was found. |
1653 StateItem next = state.getNext().copyFrom(item, nextName, -1); | 1618 StateItem next = state.getNext().copyFrom(item, nextName, -1); |
1654 next.sawDecimalPoint = true; | 1619 next.sawDecimalPoint = true; |
1655 } | 1620 } |
1656 | 1621 |
1657 private static void acceptNan(int cp, StateName nextName, ParserState state, S
tateItem item) { | 1622 private static void acceptNan(int cp, StateName nextName, ParserState state, S
tateItem item) { |
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2136 * @param cp The code point to test. Returns false if cp is negative. | 2101 * @param cp The code point to test. Returns false if cp is negative. |
2137 * @param state The current {@link ParserState}, used for determining strict m
ode. | 2102 * @param state The current {@link ParserState}, used for determining strict m
ode. |
2138 * @return true if cp is bidi or whitespace in lenient mode; false otherwise. | 2103 * @return true if cp is bidi or whitespace in lenient mode; false otherwise. |
2139 */ | 2104 */ |
2140 private static boolean isIgnorable(int cp, ParserState state) { | 2105 private static boolean isIgnorable(int cp, ParserState state) { |
2141 if (cp < 0) return false; | 2106 if (cp < 0) return false; |
2142 if (UNISET_BIDI.contains(cp)) return true; | 2107 if (UNISET_BIDI.contains(cp)) return true; |
2143 return state.mode == ParseMode.LENIENT && UNISET_WHITESPACE.contains(cp); | 2108 return state.mode == ParseMode.LENIENT && UNISET_WHITESPACE.contains(cp); |
2144 } | 2109 } |
2145 } | 2110 } |
LEFT | RIGHT |