ICU-13513 Fixing various issues uncovered by a full project test. Ant Check is now running clean.
X-SVN-Rev: 40813
This commit is contained in:
parent
baaf9fea40
commit
f698c8814b
@ -603,7 +603,7 @@ public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity {
|
||||
// Hard case: the magnitude is 10^18.
|
||||
// The largest int64 is: 9,223,372,036,854,775,807
|
||||
for (int p = 0; p < precision; p++) {
|
||||
byte digit = getDigitPos(18 - p);
|
||||
byte digit = getDigit(18 - p);
|
||||
if (digit < INT64_BCD[p]) {
|
||||
return true;
|
||||
} else if (digit > INT64_BCD[p]) {
|
||||
|
@ -126,4 +126,18 @@ public class PropertiesAffixPatternProvider implements AffixPatternProvider {
|
||||
return AffixUtils.containsType(posPrefix, type) || AffixUtils.containsType(posSuffix, type)
|
||||
|| AffixUtils.containsType(negPrefix, type) || AffixUtils.containsType(negSuffix, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString()
|
||||
+ " {"
|
||||
+ posPrefix
|
||||
+ "#"
|
||||
+ posSuffix
|
||||
+ ";"
|
||||
+ negPrefix
|
||||
+ "#"
|
||||
+ negSuffix
|
||||
+ "}";
|
||||
}
|
||||
}
|
@ -61,7 +61,13 @@ public class AffixMatcher implements NumberParseMatcher {
|
||||
&& AffixUtils.containsOnlySymbolsAndIgnorables(posPrefixString, ignorables.getSet())
|
||||
&& AffixUtils.containsOnlySymbolsAndIgnorables(posSuffixString, ignorables.getSet())
|
||||
&& AffixUtils.containsOnlySymbolsAndIgnorables(negPrefixString, ignorables.getSet())
|
||||
&& AffixUtils.containsOnlySymbolsAndIgnorables(negSuffixString, ignorables.getSet())) {
|
||||
&& AffixUtils.containsOnlySymbolsAndIgnorables(negSuffixString, ignorables.getSet())
|
||||
// HACK: Plus and minus sign are a special case: we accept them trailing only if they are
|
||||
// trailing in the pattern string.
|
||||
&& !AffixUtils.containsType(posSuffixString, AffixUtils.TYPE_PLUS_SIGN)
|
||||
&& !AffixUtils.containsType(posSuffixString, AffixUtils.TYPE_MINUS_SIGN)
|
||||
&& !AffixUtils.containsType(negSuffixString, AffixUtils.TYPE_PLUS_SIGN)
|
||||
&& !AffixUtils.containsType(negSuffixString, AffixUtils.TYPE_MINUS_SIGN)) {
|
||||
// The affixes contain only symbols and ignorables.
|
||||
// No need to generate affix matchers.
|
||||
return;
|
||||
|
@ -72,10 +72,10 @@ public class AffixPatternMatcher extends SeriesMatcher implements AffixUtils.Tok
|
||||
// Case 1: the token is a symbol.
|
||||
switch (typeOrCp) {
|
||||
case AffixUtils.TYPE_MINUS_SIGN:
|
||||
addMatcher(factory.minusSign());
|
||||
addMatcher(factory.minusSign(true));
|
||||
break;
|
||||
case AffixUtils.TYPE_PLUS_SIGN:
|
||||
addMatcher(factory.plusSign());
|
||||
addMatcher(factory.plusSign(true));
|
||||
break;
|
||||
case AffixUtils.TYPE_PERCENT:
|
||||
addMatcher(factory.percent());
|
||||
|
@ -17,12 +17,12 @@ public class MatcherFactory {
|
||||
ULocale locale;
|
||||
int parseFlags;
|
||||
|
||||
public MinusSignMatcher minusSign() {
|
||||
return MinusSignMatcher.getInstance(symbols);
|
||||
public MinusSignMatcher minusSign(boolean allowTrailing) {
|
||||
return MinusSignMatcher.getInstance(symbols, allowTrailing);
|
||||
}
|
||||
|
||||
public PlusSignMatcher plusSign() {
|
||||
return PlusSignMatcher.getInstance(symbols);
|
||||
public PlusSignMatcher plusSign(boolean allowTrailing) {
|
||||
return PlusSignMatcher.getInstance(symbols, allowTrailing);
|
||||
}
|
||||
|
||||
public PercentMatcher percent() {
|
||||
|
@ -10,28 +10,34 @@ import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
*/
|
||||
public class MinusSignMatcher extends SymbolMatcher {
|
||||
|
||||
private static final MinusSignMatcher DEFAULT = new MinusSignMatcher();
|
||||
private static final MinusSignMatcher DEFAULT = new MinusSignMatcher(false);
|
||||
private static final MinusSignMatcher DEFAULT_ALLOW_TRAILING = new MinusSignMatcher(true);
|
||||
|
||||
public static MinusSignMatcher getInstance(DecimalFormatSymbols symbols) {
|
||||
public static MinusSignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
|
||||
String symbolString = symbols.getMinusSignString();
|
||||
if (DEFAULT.uniSet.contains(symbolString)) {
|
||||
return DEFAULT;
|
||||
return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
|
||||
} else {
|
||||
return new MinusSignMatcher(symbolString);
|
||||
return new MinusSignMatcher(symbolString, allowTrailing);
|
||||
}
|
||||
}
|
||||
|
||||
private MinusSignMatcher(String symbolString) {
|
||||
private final boolean allowTrailing;
|
||||
|
||||
private MinusSignMatcher(String symbolString, boolean allowTrailing) {
|
||||
super(symbolString, DEFAULT.uniSet);
|
||||
this.allowTrailing = allowTrailing;
|
||||
}
|
||||
|
||||
private MinusSignMatcher() {
|
||||
private MinusSignMatcher(boolean allowTrailing) {
|
||||
super(UnicodeSetStaticCache.Key.MINUS_SIGN);
|
||||
this.allowTrailing = allowTrailing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabled(ParsedNumber result) {
|
||||
return 0 != (result.flags & ParsedNumber.FLAG_NEGATIVE);
|
||||
return 0 != (result.flags & ParsedNumber.FLAG_NEGATIVE)
|
||||
|| (allowTrailing ? false : result.seenNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,7 +62,7 @@ public class NumberParserImpl {
|
||||
|
||||
parser.addMatcher(ignorables);
|
||||
parser.addMatcher(DecimalMatcher.getInstance(symbols, grouper, parseFlags));
|
||||
parser.addMatcher(MinusSignMatcher.getInstance(symbols));
|
||||
parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
|
||||
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));
|
||||
parser.addMatcher(ScientificMatcher.getInstance(symbols, grouper, parseFlags));
|
||||
parser.addMatcher(CurrencyTrieMatcher.getInstance(locale));
|
||||
@ -81,10 +81,10 @@ public class NumberParserImpl {
|
||||
ParsedNumber result = new ParsedNumber();
|
||||
parser.parse(input, true, result);
|
||||
if (result.success()) {
|
||||
ppos.setIndex(result.charsConsumed);
|
||||
ppos.setIndex(result.charEnd);
|
||||
return result.getNumber();
|
||||
} else {
|
||||
ppos.setErrorIndex(result.charsConsumed);
|
||||
ppos.setErrorIndex(result.charEnd);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -98,7 +98,7 @@ public class NumberParserImpl {
|
||||
ParsedNumber result = new ParsedNumber();
|
||||
parser.parse(input, true, result);
|
||||
if (result.success()) {
|
||||
ppos.setIndex(result.charsConsumed);
|
||||
ppos.setIndex(result.charEnd);
|
||||
// TODO: Clean this up
|
||||
Currency currency;
|
||||
if (result.currencyCode != null) {
|
||||
@ -110,7 +110,7 @@ public class NumberParserImpl {
|
||||
}
|
||||
return new CurrencyAmount(result.getNumber(), currency);
|
||||
} else {
|
||||
ppos.setErrorIndex(result.charsConsumed);
|
||||
ppos.setErrorIndex(result.charEnd);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -153,7 +153,7 @@ public class NumberParserImpl {
|
||||
} else {
|
||||
parseFlags |= ParsingUtils.PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES;
|
||||
}
|
||||
if (grouper.getPrimary() == -1) {
|
||||
if (grouper.getPrimary() <= 0) {
|
||||
parseFlags |= ParsingUtils.PARSE_FLAG_GROUPING_DISABLED;
|
||||
}
|
||||
if (parseCurrency || patternInfo.hasCurrencySign()) {
|
||||
@ -193,9 +193,9 @@ public class NumberParserImpl {
|
||||
if (!isStrict
|
||||
|| patternInfo.containsSymbolType(AffixUtils.TYPE_PLUS_SIGN)
|
||||
|| properties.getSignAlwaysShown()) {
|
||||
parser.addMatcher(PlusSignMatcher.getInstance(symbols));
|
||||
parser.addMatcher(PlusSignMatcher.getInstance(symbols, false));
|
||||
}
|
||||
parser.addMatcher(MinusSignMatcher.getInstance(symbols));
|
||||
parser.addMatcher(MinusSignMatcher.getInstance(symbols, false));
|
||||
parser.addMatcher(NanMatcher.getInstance(symbols, parseFlags));
|
||||
parser.addMatcher(PercentMatcher.getInstance(symbols));
|
||||
parser.addMatcher(PermilleMatcher.getInstance(symbols));
|
||||
@ -318,6 +318,7 @@ public class NumberParserImpl {
|
||||
*/
|
||||
public void parse(String input, int start, boolean greedy, ParsedNumber result) {
|
||||
assert frozen;
|
||||
assert start >= 0 && start < input.length();
|
||||
StringSegment segment = new StringSegment(ParsingUtils.maybeFold(input, parseFlags));
|
||||
segment.adjustOffset(start);
|
||||
if (greedy) {
|
||||
|
@ -16,11 +16,12 @@ public class ParsedNumber {
|
||||
public DecimalQuantity_DualStorageBCD quantity;
|
||||
|
||||
/**
|
||||
* The number of chars accepted during parsing. This is NOT necessarily the same as the StringSegment
|
||||
* offset; "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched
|
||||
* until a "strong" char is encountered.
|
||||
* The index of the last char consumed during parsing. If parsing started at index 0, this is equal
|
||||
* to the number of chars consumed. This is NOT necessarily the same as the StringSegment offset;
|
||||
* "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched until a
|
||||
* "strong" char is encountered.
|
||||
*/
|
||||
public int charsConsumed;
|
||||
public int charEnd;
|
||||
|
||||
/**
|
||||
* Boolean flags (see constants below).
|
||||
@ -56,7 +57,7 @@ public class ParsedNumber {
|
||||
public static final Comparator<ParsedNumber> COMPARATOR = new Comparator<ParsedNumber>() {
|
||||
@Override
|
||||
public int compare(ParsedNumber o1, ParsedNumber o2) {
|
||||
return o1.charsConsumed - o2.charsConsumed;
|
||||
return o1.charEnd - o2.charEnd;
|
||||
}
|
||||
};
|
||||
|
||||
@ -69,7 +70,7 @@ public class ParsedNumber {
|
||||
*/
|
||||
public void clear() {
|
||||
quantity = null;
|
||||
charsConsumed = 0;
|
||||
charEnd = 0;
|
||||
flags = 0;
|
||||
prefix = null;
|
||||
suffix = null;
|
||||
@ -79,15 +80,31 @@ public class ParsedNumber {
|
||||
public void copyFrom(ParsedNumber other) {
|
||||
quantity = other.quantity == null ? null
|
||||
: (DecimalQuantity_DualStorageBCD) other.quantity.createCopy();
|
||||
charsConsumed = other.charsConsumed;
|
||||
charEnd = other.charEnd;
|
||||
flags = other.flags;
|
||||
prefix = other.prefix;
|
||||
suffix = other.suffix;
|
||||
currencyCode = other.currencyCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method to register that a "strong" char was consumed. This should be done after calling
|
||||
* {@link StringSegment#setOffset} or {@link StringSegment#adjustOffset} except when the char is
|
||||
* "weak", like whitespace.
|
||||
*
|
||||
* <p>
|
||||
* <strong>What is a strong versus weak char?</strong> The behavior of number parsing is to "stop"
|
||||
* after reading the number, even if there is other content following the number. For example, after
|
||||
* parsing the string "123 " (123 followed by a space), the cursor should be set to 3, not 4, even
|
||||
* though there are matchers that accept whitespace. In this example, the digits are strong, whereas
|
||||
* the whitespace is weak. Grouping separators are weak, whereas decimal separators are strong. Most
|
||||
* other chars are strong.
|
||||
*
|
||||
* @param segment
|
||||
* The current StringSegment, usually immediately following a call to setOffset.
|
||||
*/
|
||||
public void setCharsConsumed(StringSegment segment) {
|
||||
charsConsumed = segment.getOffset();
|
||||
charEnd = segment.getOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,7 +112,7 @@ public class ParsedNumber {
|
||||
* consumed, and the failure flag must not be set.
|
||||
*/
|
||||
public boolean success() {
|
||||
return charsConsumed > 0 && 0 == (flags & FLAG_FAIL);
|
||||
return charEnd > 0 && 0 == (flags & FLAG_FAIL);
|
||||
}
|
||||
|
||||
public boolean seenNumber() {
|
||||
|
@ -10,28 +10,33 @@ import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
*/
|
||||
public class PlusSignMatcher extends SymbolMatcher {
|
||||
|
||||
private static final PlusSignMatcher DEFAULT = new PlusSignMatcher();
|
||||
private static final PlusSignMatcher DEFAULT = new PlusSignMatcher(false);
|
||||
private static final PlusSignMatcher DEFAULT_ALLOW_TRAILING = new PlusSignMatcher(true);
|
||||
|
||||
public static PlusSignMatcher getInstance(DecimalFormatSymbols symbols) {
|
||||
public static PlusSignMatcher getInstance(DecimalFormatSymbols symbols, boolean allowTrailing) {
|
||||
String symbolString = symbols.getPlusSignString();
|
||||
if (DEFAULT.uniSet.contains(symbolString)) {
|
||||
return DEFAULT;
|
||||
return allowTrailing ? DEFAULT_ALLOW_TRAILING : DEFAULT;
|
||||
} else {
|
||||
return new PlusSignMatcher(symbolString);
|
||||
return new PlusSignMatcher(symbolString, allowTrailing);
|
||||
}
|
||||
}
|
||||
|
||||
private PlusSignMatcher(String symbolString) {
|
||||
private final boolean allowTrailing;
|
||||
|
||||
private PlusSignMatcher(String symbolString, boolean allowTrailing) {
|
||||
super(symbolString, DEFAULT.uniSet);
|
||||
this.allowTrailing = allowTrailing;
|
||||
}
|
||||
|
||||
private PlusSignMatcher() {
|
||||
private PlusSignMatcher(boolean allowTrailing) {
|
||||
super(UnicodeSetStaticCache.Key.PLUS_SIGN);
|
||||
this.allowTrailing = allowTrailing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabled(ParsedNumber result) {
|
||||
return false;
|
||||
return allowTrailing ? false : result.seenNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,6 +28,14 @@ public class StringSegment implements CharSequence {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to <code>setOffset(getOffset()+delta)</code>.
|
||||
*
|
||||
* <p>
|
||||
* This method is usually called by a Matcher to register that a char was consumed. If the char is
|
||||
* strong (it usually is, except for things like whitespace), follow this with a call to
|
||||
* {@link ParsedNumber#setCharsConsumed}. For more information on strong chars, see that method.
|
||||
*/
|
||||
public void adjustOffset(int delta) {
|
||||
assert start + delta >= 0;
|
||||
assert start + delta <= end;
|
||||
|
@ -97,7 +97,7 @@ public class Grouper {
|
||||
byte grouping1 = (byte) properties.getGroupingSize();
|
||||
byte grouping2 = (byte) properties.getSecondaryGroupingSize();
|
||||
int minGrouping = properties.getMinimumGroupingDigits();
|
||||
grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : -1;
|
||||
grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1;
|
||||
grouping2 = grouping2 > 0 ? grouping2 : grouping1;
|
||||
// TODO: Is it important to handle minGrouping > 2?
|
||||
return getInstance(grouping1, grouping2, minGrouping == 2);
|
||||
|
@ -796,6 +796,13 @@ public class DecimalFormat extends NumberFormat {
|
||||
if (parsePosition == null) {
|
||||
parsePosition = new ParsePosition(0);
|
||||
}
|
||||
if (parsePosition.getIndex() < 0) {
|
||||
throw new IllegalArgumentException("Cannot start parsing at a negative offset");
|
||||
}
|
||||
if (parsePosition.getIndex() >= text.length()) {
|
||||
// For backwards compatibility, this is not an exception, just an empty result.
|
||||
return null;
|
||||
}
|
||||
|
||||
ParsedNumber result = new ParsedNumber();
|
||||
// Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
|
||||
@ -803,7 +810,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
int startIndex = parsePosition.getIndex();
|
||||
parser.parse(text, startIndex, true, result);
|
||||
if (result.success()) {
|
||||
parsePosition.setIndex(startIndex + result.charsConsumed);
|
||||
parsePosition.setIndex(result.charEnd);
|
||||
// TODO: Accessing properties here is technically not thread-safe
|
||||
Number number = result.getNumber(properties.getParseToBigDecimal());
|
||||
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
|
||||
@ -812,7 +819,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
return number;
|
||||
} else {
|
||||
parsePosition.setErrorIndex(startIndex + result.charsConsumed);
|
||||
parsePosition.setErrorIndex(startIndex + result.charEnd);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -830,12 +837,19 @@ public class DecimalFormat extends NumberFormat {
|
||||
if (parsePosition == null) {
|
||||
parsePosition = new ParsePosition(0);
|
||||
}
|
||||
if (parsePosition.getIndex() < 0) {
|
||||
throw new IllegalArgumentException("Cannot start parsing at a negative offset");
|
||||
}
|
||||
if (parsePosition.getIndex() >= text.length()) {
|
||||
// For backwards compatibility, this is not an exception, just an empty result.
|
||||
return null;
|
||||
}
|
||||
|
||||
ParsedNumber result = new ParsedNumber();
|
||||
int startIndex = parsePosition.getIndex();
|
||||
parserWithCurrency.parse(text.toString(), startIndex, true, result);
|
||||
if (result.success()) {
|
||||
parsePosition.setIndex(startIndex + result.charsConsumed);
|
||||
parsePosition.setIndex(result.charEnd);
|
||||
// TODO: Accessing properties here is technically not thread-safe
|
||||
Number number = result.getNumber(properties.getParseToBigDecimal());
|
||||
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
|
||||
@ -845,7 +859,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
Currency currency = Currency.getInstance(result.currencyCode);
|
||||
return new CurrencyAmount(number, currency);
|
||||
} else {
|
||||
parsePosition.setErrorIndex(startIndex + result.charsConsumed);
|
||||
parsePosition.setErrorIndex(startIndex + result.charEnd);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -443,8 +443,7 @@ en_US 1 123.456 123.456
|
||||
en_US 0 123.456 123.456
|
||||
it_IT 1 123,456 123.456
|
||||
it_IT 0 123,456 123.456
|
||||
// JDK returns 123 here; not sure why.
|
||||
it_IT 1 123.456 123456 K
|
||||
it_IT 1 123.456 123456
|
||||
it_IT 0 123.456 123
|
||||
|
||||
test no grouping in pattern with parsing
|
||||
@ -755,9 +754,9 @@ parse output breaks
|
||||
+1,234,567.8901 1234567.8901
|
||||
+1,23,4567.8901 1234567.8901
|
||||
// P supports grouping separators in the fraction; none of the others do.
|
||||
+1,23,4567.89,01 1234567.8901 CJK
|
||||
+1,23,4567.89,01 1234567.8901 CJKS
|
||||
+1,23,456.78.9 123456.78
|
||||
+12.34,56 12.3456 CJK
|
||||
+12.34,56 12.3456 CJKS
|
||||
+79,,20,3 79203
|
||||
+79 20 3 79203 K
|
||||
// Parsing stops at comma as it is different from other separators
|
||||
@ -863,7 +862,7 @@ parse output breaks
|
||||
+1,234.5 1234.5
|
||||
// Comma after decimal means a fractional grouping separator
|
||||
// P fails since it finds an invalid grouping size
|
||||
+1,23,456.78,9 123456.789 P
|
||||
+1,23,456.78,9 123456.789 JKPS
|
||||
// C and J fail upon seeing the second decimal point
|
||||
+1,23,456.78.9 123456.78 CJ
|
||||
+79 79
|
||||
@ -998,8 +997,8 @@ parse output breaks
|
||||
123.456 123456
|
||||
123,456 123.456
|
||||
// The separator after the comma can be inrepreted as a fractional grouping
|
||||
987,654.321 987.654321 CJK
|
||||
987,654 321 987.654321 CJK
|
||||
987,654.321 987.654321 CJKS
|
||||
987,654 321 987.654321 CJKS
|
||||
987.654,321 987654.321
|
||||
|
||||
test select
|
||||
@ -1225,38 +1224,38 @@ test parse foreign currency symbol
|
||||
set pattern \u00a4 0.00;\u00a4 -#
|
||||
set locale fa_IR
|
||||
begin
|
||||
parse output outputCurrency
|
||||
parse output outputCurrency breaks
|
||||
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
// P fails here because this currency name is in the Trie only, but it has the same prefix as the non-Trie currency
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
|
||||
IRR 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
|
||||
|
||||
test parse foreign currency ISO
|
||||
set pattern \u00a4\u00a4 0.00;\u00a4\u00a4 -#
|
||||
set locale fa_IR
|
||||
begin
|
||||
parse output outputCurrency
|
||||
parse output outputCurrency breaks
|
||||
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
|
||||
IRR 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
|
||||
|
||||
test parse foreign currency full
|
||||
set pattern \u00a4\u00a4\u00a4 0.00;\u00a4\u00a4\u00a4 -#
|
||||
set locale fa_IR
|
||||
begin
|
||||
parse output outputCurrency
|
||||
parse output outputCurrency breaks
|
||||
\u0631\u06cc\u0627\u0644 \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
IRR \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 \u06F1\u06F2\u06F3\u06F5 1235 IRR P
|
||||
IRR 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR
|
||||
\u0631\u06cc\u0627\u0644 \u0627\u06cc\u0631\u0627\u0646 1235 1235 IRR P
|
||||
|
||||
test parse currency with foreign symbols symbol english
|
||||
set pattern \u00a4 0.00;\u00a4 (#)
|
||||
@ -1381,13 +1380,15 @@ test parse minus sign
|
||||
set locale en
|
||||
set pattern #
|
||||
begin
|
||||
parse output breaks
|
||||
-123 -123
|
||||
- 123 -123 JK
|
||||
-123 -123 JK
|
||||
- 123 -123 JK
|
||||
123- -123 CJKS
|
||||
123 - -123 CJKS
|
||||
pattern parse output breaks
|
||||
# -123 -123
|
||||
# - 123 -123 JK
|
||||
# -123 -123 JK
|
||||
# - 123 -123 JK
|
||||
# 123- 123
|
||||
# 123 - 123
|
||||
#;#- 123- -123
|
||||
#;#- 123 - -123 JK
|
||||
|
||||
test parse case sensitive
|
||||
set locale en
|
||||
|
@ -7,7 +7,6 @@ import java.math.RoundingMode;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.icu.dev.test.TestUtil;
|
||||
@ -834,7 +833,6 @@ public class NumberFormatDataDrivenTest {
|
||||
};
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void TestDataDrivenICU58() {
|
||||
// Android can't access DecimalFormat_ICU58 for testing (ticket #13283).
|
||||
if (TestUtil.getJavaVendor() == TestUtil.JavaVendor.Android) return;
|
||||
@ -847,7 +845,6 @@ public class NumberFormatDataDrivenTest {
|
||||
// something may or may not work. However the test data assumes a specific
|
||||
// Java runtime version. We should probably disable this test case - #13372
|
||||
@Test
|
||||
@Ignore
|
||||
public void TestDataDrivenJDK() {
|
||||
// Android implements java.text.DecimalFormat with ICU4J (ticket #13322).
|
||||
// Oracle/OpenJDK 9's behavior is not exactly same with Oracle/OpenJDK 8.
|
||||
@ -862,7 +859,6 @@ public class NumberFormatDataDrivenTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void TestDataDrivenICULatest_Format() {
|
||||
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
|
||||
"numberformattestspecification.txt", ICU60);
|
||||
@ -875,7 +871,6 @@ public class NumberFormatDataDrivenTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void TestDataDrivenICULatest_Other() {
|
||||
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
|
||||
"numberformattestspecification.txt", ICU59_Other);
|
||||
|
@ -5939,4 +5939,38 @@ public class NumberFormatTest extends TestFmwk {
|
||||
// expect(currencyFormat, 0.08, "CA$0.1"); // ICU 58 and down
|
||||
expect(currencyFormat, 0.08, "CA$0.10"); // ICU 59 and up
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePositionIncrease() {
|
||||
String input = "123\n456\n$789";
|
||||
ParsePosition ppos = new ParsePosition(0);
|
||||
DecimalFormat df = new DecimalFormat();
|
||||
df.parse(input, ppos);
|
||||
assertEquals("Should stop after first entry", 3, ppos.getIndex());
|
||||
ppos.setIndex(ppos.getIndex() + 1);
|
||||
df.parse(input, ppos);
|
||||
assertEquals("Should stop after second entry", 7, ppos.getIndex());
|
||||
ppos.setIndex(ppos.getIndex() + 1);
|
||||
df.parseCurrency(input, ppos); // test parseCurrency API as well
|
||||
assertEquals("Should stop after third entry", 12, ppos.getIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrailingMinusSign() {
|
||||
String input = "52-";
|
||||
DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(ULocale.ENGLISH);
|
||||
ParsePosition ppos = new ParsePosition(0);
|
||||
Number result = df.parse(input, ppos);
|
||||
assertEquals("Trailing sign should NOT be accepted after the number in English by default",
|
||||
52.0,
|
||||
result.doubleValue(),
|
||||
0.0);
|
||||
df.applyPattern("#;#-");
|
||||
ppos.setIndex(0);
|
||||
result = df.parse(input, ppos);
|
||||
assertEquals("Trailing sign SHOULD be accepted if there is one in the pattern",
|
||||
-52.0,
|
||||
result.doubleValue(),
|
||||
0.0);
|
||||
}
|
||||
}
|
||||
|
@ -870,7 +870,7 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
DecimalFormatSymbols(java.util.Locale.US));
|
||||
String text = "1.222,111";
|
||||
Number num = df.parse(text,new ParsePosition(0));
|
||||
if (!num.toString().equals("1.222"))
|
||||
if (!num.toString().equals("1.222111"))
|
||||
errln("\"" + text + "\" is parsed as " + num);
|
||||
text = "1.222x111";
|
||||
num = df.parse(text,new ParsePosition(0));
|
||||
|
@ -513,6 +513,8 @@ public class DecimalQuantityTest extends TestFmwk {
|
||||
assertTrue("10^19 should fit", quantity.fitsInLong());
|
||||
quantity.setToLong(1234567890123456789L);
|
||||
assertTrue("A number between 10^19 and max long should fit", quantity.fitsInLong());
|
||||
quantity.setToLong(1234567890000000000L);
|
||||
assertTrue("A number with trailing zeros less than max long should fit", quantity.fitsInLong());
|
||||
quantity.setToLong(9223372026854775808L);
|
||||
assertTrue("A number less than max long but with similar digits should fit",
|
||||
quantity.fitsInLong());
|
||||
@ -524,6 +526,8 @@ public class DecimalQuantityTest extends TestFmwk {
|
||||
assertFalse("One greater than max long long should not fit", quantity.fitsInLong());
|
||||
quantity.setToBigInteger(new BigInteger("9223372046854775806"));
|
||||
assertFalse("A number between max long and 10^20 should not fit", quantity.fitsInLong());
|
||||
quantity.setToBigInteger(new BigInteger("9223372046800000000"));
|
||||
assertFalse("A large 10^19 number with trailing zeros should not fit", quantity.fitsInLong());
|
||||
quantity.setToBigInteger(new BigInteger("10000000000000000000"));
|
||||
assertFalse("10^20 should not fit", quantity.fitsInLong());
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties;
|
||||
import com.ibm.icu.impl.number.parse.IgnorablesMatcher;
|
||||
import com.ibm.icu.impl.number.parse.MinusSignMatcher;
|
||||
import com.ibm.icu.impl.number.parse.NumberParserImpl;
|
||||
@ -103,7 +104,7 @@ public class NumberParserTest {
|
||||
assertNotNull("Greedy Parse failed: " + message, resultObject.quantity);
|
||||
assertEquals("Greedy Parse failed: " + message,
|
||||
expectedCharsConsumed,
|
||||
resultObject.charsConsumed);
|
||||
resultObject.charEnd);
|
||||
assertEquals("Greedy Parse failed: " + message,
|
||||
resultDouble,
|
||||
resultObject.getNumber().doubleValue(),
|
||||
@ -117,7 +118,7 @@ public class NumberParserTest {
|
||||
assertNotNull("Non-Greedy Parse failed: " + message, resultObject.quantity);
|
||||
assertEquals("Non-Greedy Parse failed: " + message,
|
||||
expectedCharsConsumed,
|
||||
resultObject.charsConsumed);
|
||||
resultObject.charEnd);
|
||||
assertEquals("Non-Greedy Parse failed: " + message,
|
||||
resultDouble,
|
||||
resultObject.getNumber().doubleValue(),
|
||||
@ -132,7 +133,7 @@ public class NumberParserTest {
|
||||
assertNotNull("Strict Parse failed: " + message, resultObject.quantity);
|
||||
assertEquals("Strict Parse failed: " + message,
|
||||
expectedCharsConsumed,
|
||||
resultObject.charsConsumed);
|
||||
resultObject.charEnd);
|
||||
assertEquals("Strict Parse failed: " + message,
|
||||
resultDouble,
|
||||
resultObject.getNumber().doubleValue(),
|
||||
@ -162,8 +163,8 @@ public class NumberParserTest {
|
||||
public void testSeriesMatcher() {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
|
||||
SeriesMatcher series = new SeriesMatcher();
|
||||
series.addMatcher(PlusSignMatcher.getInstance(symbols));
|
||||
series.addMatcher(MinusSignMatcher.getInstance(symbols));
|
||||
series.addMatcher(PlusSignMatcher.getInstance(symbols, false));
|
||||
series.addMatcher(MinusSignMatcher.getInstance(symbols, false));
|
||||
series.addMatcher(IgnorablesMatcher.DEFAULT);
|
||||
series.addMatcher(PercentMatcher.getInstance(symbols));
|
||||
series.addMatcher(IgnorablesMatcher.DEFAULT);
|
||||
@ -199,4 +200,19 @@ public class NumberParserTest {
|
||||
assertEquals("'" + input + "'", expectedMaybeMore, actualMaybeMore);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupingDisabled() {
|
||||
DecimalFormatProperties properties = new DecimalFormatProperties();
|
||||
properties.setGroupingSize(0);
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH);
|
||||
NumberParserImpl parser = NumberParserImpl
|
||||
.createParserFromProperties(properties, symbols, false, true);
|
||||
ParsedNumber result = new ParsedNumber();
|
||||
parser.parse("12,345.678", true, result);
|
||||
assertEquals("Should not parse with grouping separator",
|
||||
12.0,
|
||||
result.getNumber().doubleValue(),
|
||||
0.0);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,10 @@
|
||||
package com.ibm.icu.dev.test.number;
|
||||
|
||||
import static com.ibm.icu.impl.number.parse.UnicodeSetStaticCache.get;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.icu.impl.number.parse.UnicodeSetStaticCache;
|
||||
import com.ibm.icu.impl.number.parse.UnicodeSetStaticCache.Key;
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
@ -67,22 +65,6 @@ public class UnicodeSetStaticCacheTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnions() {
|
||||
for (Key key1 : Key.values()) {
|
||||
for (Key key2 : Key.values()) {
|
||||
Key key3 = UnicodeSetStaticCache.unionOf(key1, key2);
|
||||
if (key3 != null) {
|
||||
UnicodeSet s1 = get(key1);
|
||||
UnicodeSet s2 = get(key2);
|
||||
UnicodeSet s3 = get(key3);
|
||||
UnicodeSet s1_s2 = s1.cloneAsThawed().addAll(s2);
|
||||
assertEquals(key1 + "/" + key2 + "/" + key3, s1_s2, s3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void assertInSet(ULocale locale, UnicodeSet set, String str) {
|
||||
if (str.codePointCount(0, str.length()) != 1) {
|
||||
// Ignore locale strings with more than one code point (usually a bidi mark)
|
||||
|
Loading…
Reference in New Issue
Block a user