ICU-10368 String digit/symbol support in DecimalFormatSymbols - merged from the work branch.
X-SVN-Rev: 39202
This commit is contained in:
parent
390d736f89
commit
72e1644c07
@ -30,11 +30,11 @@ public class CurrencyData {
|
||||
|
||||
public static final class CurrencyFormatInfo {
|
||||
public final String currencyPattern;
|
||||
public final char monetarySeparator;
|
||||
public final char monetaryGroupingSeparator;
|
||||
public final String monetarySeparator;
|
||||
public final String monetaryGroupingSeparator;
|
||||
|
||||
public CurrencyFormatInfo(String currencyPattern, char monetarySeparator,
|
||||
char monetaryGroupingSeparator) {
|
||||
public CurrencyFormatInfo(String currencyPattern, String monetarySeparator,
|
||||
String monetaryGroupingSeparator) {
|
||||
this.currencyPattern = currencyPattern;
|
||||
this.monetarySeparator = monetarySeparator;
|
||||
this.monetaryGroupingSeparator = monetaryGroupingSeparator;
|
||||
@ -93,10 +93,12 @@ public class CurrencyData {
|
||||
temp = (CurrencyDisplayInfoProvider) clzz.newInstance();
|
||||
} catch (Throwable t) {
|
||||
temp = new CurrencyDisplayInfoProvider() {
|
||||
@Override
|
||||
public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) {
|
||||
return DefaultInfo.getWithFallback(withFallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasData() {
|
||||
return false;
|
||||
}
|
||||
|
@ -896,9 +896,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
addPadding(result, fieldPosition, prefixLen, suffixLen);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int precision = precision(false);
|
||||
|
||||
|
||||
// This is to fix rounding for scientific notation. See ticket:10542.
|
||||
// This code should go away when a permanent fix is done for ticket:9931.
|
||||
//
|
||||
@ -957,7 +957,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
return toDigitList(number).getDouble();
|
||||
}
|
||||
|
||||
|
||||
@Deprecated
|
||||
DigitList toDigitList(double number) {
|
||||
DigitList result = new DigitList();
|
||||
@ -1129,7 +1129,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
digitList.set(number, precision(true));
|
||||
// Issue 11808
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number, result, fieldPosition, isNegative, true, parseAttr);
|
||||
}
|
||||
@ -1164,7 +1164,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
digitList.set(number, precision(true));
|
||||
// For issue 11808.
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number.intValue(), result, fieldPosition, number.signum() < 0, true,
|
||||
parseAttr);
|
||||
@ -1198,7 +1198,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
!areSignificantDigitsUsed());
|
||||
// For issue 11808.
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
|
||||
false, parseAttr);
|
||||
@ -1231,7 +1231,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
!areSignificantDigitsUsed());
|
||||
// For issue 11808.
|
||||
if (digitList.wasRounded() && roundingMode == BigDecimal.ROUND_UNNECESSARY) {
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
throw new ArithmeticException("Rounding necessary");
|
||||
}
|
||||
return subformat(number.doubleValue(), result, fieldPosition, number.signum() < 0,
|
||||
false, false);
|
||||
@ -1292,7 +1292,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
// get the visible fractions and the number of fraction digits.
|
||||
return getFixedDecimal(number, digitList);
|
||||
}
|
||||
|
||||
|
||||
FixedDecimal getFixedDecimal(double number, DigitList dl) {
|
||||
int fractionalDigitsInDigitList = dl.count - dl.decimalAt;
|
||||
int v;
|
||||
@ -1421,12 +1421,12 @@ public class DecimalFormat extends NumberFormat {
|
||||
FieldPosition fieldPosition,
|
||||
boolean isInteger,
|
||||
boolean parseAttr) {
|
||||
char [] digits = symbols.getDigitsLocal();
|
||||
String[] digits = symbols.getDigitStrings();
|
||||
|
||||
char grouping = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
|
||||
symbols.getGroupingSeparator(): symbols.getMonetaryGroupingSeparator();
|
||||
char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
|
||||
symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
|
||||
String grouping = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
|
||||
symbols.getGroupingSeparatorString(): symbols.getMonetaryGroupingSeparatorString();
|
||||
String decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
|
||||
symbols.getDecimalSeparatorString() : symbols.getMonetaryDecimalSeparatorString();
|
||||
boolean useSigDig = areSignificantDigitsUsed();
|
||||
int maxIntDig = getMaximumIntegerDigits();
|
||||
int minIntDig = getMinimumIntegerDigits();
|
||||
@ -1506,14 +1506,14 @@ public class DecimalFormat extends NumberFormat {
|
||||
fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
|
||||
|
||||
// This handles the special case of formatting 0. For zero only, we count the
|
||||
// zero to the left of the decimal point as one signficant digit. Ordinarily we
|
||||
// do not count any leading 0's as significant. If the number we are formatting
|
||||
// is not zero, then either sigCount or digits.getCount() will be non-zero.
|
||||
if (sigCount == 0 && digitList.count == 0) {
|
||||
sigCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether or not there are any printable fractional digits. If
|
||||
// we've used up the digits we know there aren't.
|
||||
@ -1629,9 +1629,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
private void subformatExponential(StringBuffer result,
|
||||
FieldPosition fieldPosition,
|
||||
boolean parseAttr) {
|
||||
char [] digits = symbols.getDigitsLocal();
|
||||
char decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
|
||||
symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
|
||||
String[] digits = symbols.getDigitStringsLocal();
|
||||
String decimal = currencySignCount == CURRENCY_SIGN_COUNT_ZERO ?
|
||||
symbols.getDecimalSeparatorString() : symbols.getMonetaryDecimalSeparatorString();
|
||||
boolean useSigDig = areSignificantDigitsUsed();
|
||||
int maxIntDig = getMaximumIntegerDigits();
|
||||
int minIntDig = getMinimumIntegerDigits();
|
||||
@ -1777,7 +1777,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
addAttribute(Field.DECIMAL_SEPARATOR, decimalSeparatorBegin, result.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Record field information
|
||||
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
|
||||
if (fieldPosition.getEndIndex() < 0) {
|
||||
@ -1841,7 +1841,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
}
|
||||
result.append(symbols.getMinusString());
|
||||
result.append(symbols.getMinusSignString());
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
@ -1855,7 +1855,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
}
|
||||
result.append(symbols.getPlusString());
|
||||
result.append(symbols.getPlusSignString());
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
@ -2353,7 +2353,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
0xFF0C, 0xFF0C,
|
||||
0xFF0E, 0xFF0E,
|
||||
0xFF61, 0xFF61).freeze();
|
||||
|
||||
|
||||
static final UnicodeSet minusSigns =
|
||||
new UnicodeSet(
|
||||
0x002D, 0x002D,
|
||||
@ -2363,7 +2363,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
0x2796, 0x2796,
|
||||
0xFE63, 0xFE63,
|
||||
0xFF0D, 0xFF0D).freeze();
|
||||
|
||||
|
||||
static final UnicodeSet plusSigns =
|
||||
new UnicodeSet(
|
||||
0x002B, 0x002B,
|
||||
@ -2373,7 +2373,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
0xFB29, 0xFB29,
|
||||
0xFE62, 0xFE62,
|
||||
0xFF0B, 0xFF0B).freeze();
|
||||
|
||||
|
||||
// equivalent grouping and decimal support
|
||||
static final boolean skipExtendedSeparatorParsing = ICUConfig.get(
|
||||
"com.ibm.icu.text.DecimalFormat.SkipExtendedSeparatorParsing", "false")
|
||||
@ -2460,25 +2460,22 @@ public class DecimalFormat extends NumberFormat {
|
||||
// DigitList, and adjust the exponent as needed.
|
||||
|
||||
digits.decimalAt = digits.count = 0;
|
||||
char [] digitSymbols = symbols.getDigitsLocal();
|
||||
char decimal = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
|
||||
symbols.getDecimalSeparator() : symbols.getMonetaryDecimalSeparator();
|
||||
char grouping = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
|
||||
symbols.getGroupingSeparator() : symbols.getMonetaryGroupingSeparator();
|
||||
String decimal = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
|
||||
symbols.getDecimalSeparatorString() : symbols.getMonetaryDecimalSeparatorString();
|
||||
String grouping = (currencySignCount == CURRENCY_SIGN_COUNT_ZERO) ?
|
||||
symbols.getGroupingSeparatorString() : symbols.getMonetaryGroupingSeparatorString();
|
||||
|
||||
String exponentSep = symbols.getExponentSeparator();
|
||||
boolean sawDecimal = false;
|
||||
boolean sawGrouping = false;
|
||||
boolean sawExponent = false;
|
||||
boolean sawDigit = false;
|
||||
long exponent = 0; // Set to the exponent value, if any
|
||||
int digit = 0;
|
||||
|
||||
// strict parsing
|
||||
boolean strictParse = isParseStrict();
|
||||
boolean strictFail = false; // did we exit with a strict parse failure?
|
||||
int lastGroup = -1; // where did we last see a grouping separator?
|
||||
int digitStart = position; // where did the digit start?
|
||||
int groupedDigitCount = 0; // tracking count of digits delimited by grouping separator
|
||||
int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2;
|
||||
|
||||
UnicodeSet decimalEquiv = skipExtendedSeparatorParsing ? UnicodeSet.EMPTY :
|
||||
@ -2490,136 +2487,137 @@ public class DecimalFormat extends NumberFormat {
|
||||
// the maximum allowable digits is reached.
|
||||
int digitCount = 0;
|
||||
|
||||
int backup = -1;
|
||||
int ch;
|
||||
for (; position < text.length(); position += UTF16.getCharCount(ch)) {
|
||||
ch = UTF16.charAt(text,position);
|
||||
int backup = -1; // used for preserving the last confirmed position
|
||||
int[] parsedDigit = {-1}; // allocates int[1] for parsing a single digit
|
||||
|
||||
|
||||
// We recognize all digit ranges, not only the Latin digit range
|
||||
// '0'..'9'. We do so by using the UCharacter.digit() method, which
|
||||
// converts a valid Unicode digit to the range 0..9.
|
||||
//
|
||||
// The character 'ch' may be a digit. If so, place its value from 0 to 9
|
||||
// in 'digit'. First try using the locale digit, which may or MAY NOT be a
|
||||
// standard Unicode digit range. If this fails, try using the standard
|
||||
// Unicode digit ranges by calling UCharacter.digit(). If this also fails,
|
||||
// digit will have a value outside the range 0..9.
|
||||
digit = ch - digitSymbols[0];
|
||||
if (digit < 0 || digit > 9)
|
||||
digit = UCharacter.digit(ch, 10);
|
||||
if (digit < 0 || digit > 9) {
|
||||
for ( digit = 0 ; digit < 10 ; digit++) {
|
||||
if ( ch == digitSymbols[digit] )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (digit == 0) {
|
||||
while (position < text.length()) {
|
||||
// Check if the sequence at the current position matches a decimal digit
|
||||
int matchLen = matchesDigit(text, position, parsedDigit);
|
||||
if (matchLen > 0) {
|
||||
// matched a digit
|
||||
// Cancel out backup setting (see grouping handler below)
|
||||
if (strictParse && backup != -1) {
|
||||
// comma followed by digit, so group before comma is a secondary
|
||||
// group. If there was a group separator before that, the group
|
||||
// must == the secondary group length, else it can be <= the the
|
||||
// secondary group length.
|
||||
if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
|
||||
|| (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
|
||||
strictFail = true;
|
||||
break;
|
||||
if (backup != -1) {
|
||||
if (strictParse) {
|
||||
// comma followed by digit, so group before comma is a secondary
|
||||
// group. If there was a group separator before that, the group
|
||||
// must == the secondary group length, else it can be <= the the
|
||||
// secondary group length.
|
||||
if ((lastGroup != -1 && groupedDigitCount != gs2)
|
||||
|| (lastGroup == -1 && groupedDigitCount > gs2)) {
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
lastGroup = backup;
|
||||
groupedDigitCount = 0;
|
||||
}
|
||||
backup = -1; // Do this BEFORE continue statement below!!!
|
||||
sawDigit = true;
|
||||
|
||||
// Handle leading zeros
|
||||
if (digits.count == 0) {
|
||||
groupedDigitCount++;
|
||||
position += matchLen;
|
||||
backup = -1;
|
||||
sawDigit = true;
|
||||
if (parsedDigit[0] == 0 && digits.count == 0) {
|
||||
// Handle leading zeros
|
||||
if (!sawDecimal) {
|
||||
// Ignore leading zeros in integer part of number.
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we have seen the decimal, but no significant digits yet,
|
||||
// then we account for leading zeros by decrementing the
|
||||
// digits.decimalAt into negative values.
|
||||
--digits.decimalAt;
|
||||
} else {
|
||||
++digitCount;
|
||||
digits.append((char) (digit + '0'));
|
||||
}
|
||||
} else if (digit > 0 && digit <= 9) // [sic] digit==0 handled above
|
||||
{
|
||||
if (strictParse) {
|
||||
if (backup != -1) {
|
||||
if ((lastGroup != -1 && countCodePoints(text, lastGroup, backup) - 1 != gs2)
|
||||
|| (lastGroup == -1 && countCodePoints(text, digitStart, position) - 1 > gs2)) {
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
lastGroup = backup;
|
||||
}
|
||||
digits.append((char) (parsedDigit[0] + '0'));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
sawDigit = true;
|
||||
++digitCount;
|
||||
digits.append((char) (digit + '0'));
|
||||
|
||||
// Cancel out backup setting (see grouping handler below)
|
||||
backup = -1;
|
||||
} else if (ch == decimal) {
|
||||
// Check if the sequence at the current position matches locale's decimal separator
|
||||
int decimalStrLen = decimal.length();
|
||||
if (text.regionMatches(position, decimal, 0, decimalStrLen)) {
|
||||
// matched a decimal separator
|
||||
if (strictParse) {
|
||||
if (backup != -1 ||
|
||||
(lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
|
||||
(lastGroup != -1 && groupedDigitCount != groupingSize)) {
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're only parsing integers, or if we ALREADY saw the decimal,
|
||||
// then don't parse this one.
|
||||
if (isParseIntegerOnly() || sawDecimal) {
|
||||
break;
|
||||
}
|
||||
|
||||
digits.decimalAt = digitCount; // Not digits.count!
|
||||
sawDecimal = true;
|
||||
} else if (isGroupingUsed() && ch == grouping) {
|
||||
if (sawDecimal) {
|
||||
break;
|
||||
}
|
||||
if (strictParse) {
|
||||
if ((!sawDigit || backup != -1)) {
|
||||
// leading group, or two group separators in a row
|
||||
strictFail = true;
|
||||
position += decimalStrLen;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isGroupingUsed()) {
|
||||
// Check if the sequence at the current position matches locale's grouping separator
|
||||
int groupingStrLen = grouping.length();
|
||||
if (text.regionMatches(position, grouping, 0, groupingStrLen)) {
|
||||
if (sawDecimal) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strictParse) {
|
||||
if ((!sawDigit || backup != -1)) {
|
||||
// leading group, or two group separators in a row
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore grouping characters, if we are using them, but require that
|
||||
// they be followed by a digit. Otherwise we backup and reprocess
|
||||
// them.
|
||||
backup = position;
|
||||
position += groupingStrLen;
|
||||
sawGrouping = true;
|
||||
continue;
|
||||
}
|
||||
// Ignore grouping characters, if we are using them, but require that
|
||||
// they be followed by a digit. Otherwise we backup and reprocess
|
||||
// them.
|
||||
backup = position;
|
||||
sawGrouping = true;
|
||||
} else if (!sawDecimal && decimalEquiv.contains(ch)) {
|
||||
}
|
||||
|
||||
// Check if the code point at the current position matches one of decimal/grouping equivalent group chars
|
||||
int cp = text.codePointAt(position);
|
||||
if (!sawDecimal && decimalEquiv.contains(cp)) {
|
||||
// matched a decimal separator
|
||||
if (strictParse) {
|
||||
if (backup != -1 ||
|
||||
(lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1)) {
|
||||
(lastGroup != -1 && groupedDigitCount != groupingSize)) {
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we're only parsing integers, then don't parse this one.
|
||||
if (isParseIntegerOnly())
|
||||
|
||||
// If we're only parsing integers, or if we ALREADY saw the decimal,
|
||||
// then don't parse this one.
|
||||
if (isParseIntegerOnly() || sawDecimal) {
|
||||
break;
|
||||
}
|
||||
|
||||
digits.decimalAt = digitCount; // Not digits.count!
|
||||
|
||||
// Once we see a decimal separator character, we only accept that
|
||||
// decimal separator character from then on.
|
||||
decimal = (char) ch;
|
||||
decimal = String.valueOf(Character.toChars(cp));
|
||||
|
||||
sawDecimal = true;
|
||||
} else if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(ch)) {
|
||||
position += Character.charCount(cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isGroupingUsed() && !sawGrouping && groupEquiv.contains(cp)) {
|
||||
// matched a grouping separator
|
||||
if (sawDecimal) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (strictParse) {
|
||||
if ((!sawDigit || backup != -1)) {
|
||||
// leading group, or two group separators in a row
|
||||
@ -2627,25 +2625,33 @@ public class DecimalFormat extends NumberFormat {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Once we see a grouping character, we only accept that grouping
|
||||
// character from then on.
|
||||
grouping = (char) ch;
|
||||
grouping = String.valueOf(Character.toChars(cp));
|
||||
|
||||
// Ignore grouping characters, if we are using them, but require that
|
||||
// they be followed by a digit. Otherwise we backup and reprocess
|
||||
// them.
|
||||
backup = position;
|
||||
position += Character.charCount(cp);
|
||||
sawGrouping = true;
|
||||
} else if (!sawExponent && text.regionMatches(true, position, exponentSep, 0, exponentSep.length())) {
|
||||
// Parse sign, if present
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the sequence at the current position matches locale's exponent separator
|
||||
int exponentSepStrLen = exponentSep.length();
|
||||
if (text.regionMatches(true, position, exponentSep, 0, exponentSepStrLen)) {
|
||||
// parse sign, if present
|
||||
boolean negExp = false;
|
||||
int pos = position + exponentSep.length();
|
||||
if (pos < text.length()) {
|
||||
ch = UTF16.charAt(text,pos);
|
||||
if (ch == symbols.getPlusSign()) {
|
||||
++pos;
|
||||
} else if (ch == symbols.getMinusSign()) {
|
||||
++pos;
|
||||
String plusSign = symbols.getPlusSignString();
|
||||
String minusSign = symbols.getMinusSignString();
|
||||
if (text.regionMatches(pos, plusSign, 0, plusSign.length())) {
|
||||
pos += plusSign.length();
|
||||
} else if (text.regionMatches(pos, minusSign, 0, minusSign.length())) {
|
||||
pos += minusSign.length();
|
||||
negExp = true;
|
||||
}
|
||||
}
|
||||
@ -2653,16 +2659,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
DigitList exponentDigits = new DigitList();
|
||||
exponentDigits.count = 0;
|
||||
while (pos < text.length()) {
|
||||
digit = UTF16.charAt(text,pos) - digitSymbols[0];
|
||||
if (digit < 0 || digit > 9) {
|
||||
// Can't parse "[1E0]" when pattern is "0.###E0;[0.###E0]"
|
||||
// Should update reassign the value of 'ch' in the code: digit
|
||||
// = Character.digit(ch, 10); [Richard/GCL]
|
||||
digit = UCharacter.digit(UTF16.charAt(text,pos), 10);
|
||||
}
|
||||
if (digit >= 0 && digit <= 9) {
|
||||
exponentDigits.append((char) (digit + '0'));
|
||||
pos += UTF16.getCharCount(UTF16.charAt(text,pos));
|
||||
int digitMatchLen = matchesDigit(text, pos, parsedDigit);
|
||||
if (digitMatchLen > 0) {
|
||||
exponentDigits.append((char) (parsedDigit[0] + '0'));
|
||||
pos += digitMatchLen;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -2670,11 +2670,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
|
||||
if (exponentDigits.count > 0) {
|
||||
// defer strict parse until we know we have a bona-fide exponent
|
||||
if (strictParse) {
|
||||
if (backup != -1 || lastGroup != -1) {
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
if (strictParse && sawGrouping) {
|
||||
strictFail = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Quick overflow check for exponential part. Actual limit check
|
||||
@ -2695,33 +2693,34 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
}
|
||||
position = pos; // Advance past the exponent
|
||||
sawExponent = true;
|
||||
}
|
||||
|
||||
break; // Whether we fail or succeed, we exit this loop
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// All other cases, stop parsing
|
||||
break;
|
||||
}
|
||||
|
||||
if(digits.decimalAt == 0 && isDecimalPatternMatchRequired()) {
|
||||
if(this.formatPattern.indexOf(decimal) != -1) {
|
||||
if (digits.decimalAt == 0 && isDecimalPatternMatchRequired()) {
|
||||
if (this.formatPattern.indexOf(decimal) != -1) {
|
||||
parsePosition.setIndex(oldStart);
|
||||
parsePosition.setErrorIndex(position);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (backup != -1)
|
||||
position = backup;
|
||||
|
||||
// If there was no decimal point we have an integer
|
||||
if (!sawDecimal)
|
||||
if (!sawDecimal) {
|
||||
digits.decimalAt = digitCount; // Not digits.count!
|
||||
}
|
||||
|
||||
// check for strict parse errors
|
||||
if (strictParse && !sawDecimal) {
|
||||
if (lastGroup != -1 && countCodePoints(text,lastGroup,position) != groupingSize + 1) {
|
||||
if (lastGroup != -1 && groupedDigitCount != groupingSize) {
|
||||
strictFail = true;
|
||||
}
|
||||
}
|
||||
@ -2799,21 +2798,44 @@ public class DecimalFormat extends NumberFormat {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Utility method used to count the number of codepoints
|
||||
private int countCodePoints(String str,int start, int end) {
|
||||
int count = 0;
|
||||
int index = start;
|
||||
while ( index < end ) {
|
||||
count++;
|
||||
index += UTF16.getCharCount(UTF16.charAt(str, index));
|
||||
/**
|
||||
* Check if the substring at the specified position matches a decimal digit.
|
||||
* If matched, this method sets the decimal value to <code>decVal</code> and
|
||||
* returns matched length.
|
||||
*
|
||||
* @param str The input string
|
||||
* @param start The start index
|
||||
* @param decVal Receives decimal value
|
||||
* @return Length of match, or 0 if the sequence at the position is not
|
||||
* a decimal digit.
|
||||
*/
|
||||
private int matchesDigit(String str, int start, int[] decVal) {
|
||||
String[] localeDigits = symbols.getDigitStringsLocal();
|
||||
|
||||
// Check if the sequence at the current position matches locale digits.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int digitStrLen = localeDigits[i].length();
|
||||
if (str.regionMatches(start, localeDigits[i], 0, digitStrLen)) {
|
||||
decVal[0] = i;
|
||||
return digitStrLen;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
||||
// If no locale digit match, then check if this is a Unicode digit
|
||||
int cp = str.codePointAt(start);
|
||||
decVal[0] = UCharacter.digit(cp, 10);
|
||||
if (decVal[0] >= 0) {
|
||||
return Character.charCount(cp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of characters equivalent to the given desimal separator used for
|
||||
* parsing number. This method may return an empty set.
|
||||
*/
|
||||
private UnicodeSet getEquivalentDecimals(char decimal, boolean strictParse) {
|
||||
private UnicodeSet getEquivalentDecimals(String decimal, boolean strictParse) {
|
||||
UnicodeSet equivSet = UnicodeSet.EMPTY;
|
||||
if (strictParse) {
|
||||
if (strictDotEquivalents.contains(decimal)) {
|
||||
@ -2883,31 +2905,31 @@ public class DecimalFormat extends NumberFormat {
|
||||
/**
|
||||
* Remove bidi marks from affix
|
||||
*/
|
||||
private static String trimMarksFromAffix(String affix) {
|
||||
boolean hasBidiMark = false;
|
||||
int idx = 0;
|
||||
for (; idx < affix.length(); idx++) {
|
||||
if (isBidiMark(affix.charAt(idx))) {
|
||||
hasBidiMark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasBidiMark) {
|
||||
return affix;
|
||||
}
|
||||
private static String trimMarksFromAffix(String affix) {
|
||||
boolean hasBidiMark = false;
|
||||
int idx = 0;
|
||||
for (; idx < affix.length(); idx++) {
|
||||
if (isBidiMark(affix.charAt(idx))) {
|
||||
hasBidiMark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasBidiMark) {
|
||||
return affix;
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(affix, 0, idx);
|
||||
idx++; // skip the first Bidi mark
|
||||
for (; idx < affix.length(); idx++) {
|
||||
char c = affix.charAt(idx);
|
||||
if (!isBidiMark(c)) {
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(affix, 0, idx);
|
||||
idx++; // skip the first Bidi mark
|
||||
for (; idx < affix.length(); idx++) {
|
||||
char c = affix.charAt(idx);
|
||||
if (!isBidiMark(c)) {
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length matched by the given affix, or -1 if none. Runs of white space in
|
||||
@ -3083,6 +3105,8 @@ public class DecimalFormat extends NumberFormat {
|
||||
continue;
|
||||
}
|
||||
|
||||
String affix = null;
|
||||
|
||||
switch (c) {
|
||||
case CURRENCY_SIGN:
|
||||
// since the currency names in choice format is saved the same way as
|
||||
@ -3132,15 +3156,27 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
continue;
|
||||
case PATTERN_PERCENT:
|
||||
c = symbols.getPercent();
|
||||
affix = symbols.getPercentString();
|
||||
break;
|
||||
case PATTERN_PER_MILLE:
|
||||
c = symbols.getPerMill();
|
||||
affix = symbols.getPerMillString();
|
||||
break;
|
||||
case PATTERN_MINUS:
|
||||
c = symbols.getMinusSign();
|
||||
case PATTERN_PLUS_SIGN:
|
||||
affix = symbols.getPlusSignString();
|
||||
break;
|
||||
case PATTERN_MINUS_SIGN:
|
||||
affix = symbols.getMinusSignString();
|
||||
break;
|
||||
default:
|
||||
// fall through to affix != null test, which will fail
|
||||
break;
|
||||
}
|
||||
|
||||
if (affix != null) {
|
||||
pos = match(text, pos, affix);
|
||||
continue;
|
||||
}
|
||||
|
||||
pos = match(text, pos, c);
|
||||
if (PatternProps.isWhiteSpace(c)) {
|
||||
i = skipPatternWhiteSpace(affixPat, i);
|
||||
@ -3186,6 +3222,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
for (int i = 0; i < str.length() && pos >= 0;) {
|
||||
int ch = UTF16.charAt(str, i);
|
||||
i += UTF16.getCharCount(ch);
|
||||
if (isBidiMark(ch)) {
|
||||
continue;
|
||||
}
|
||||
pos = match(text, pos, ch);
|
||||
if (PatternProps.isWhiteSpace(ch)) {
|
||||
i = skipPatternWhiteSpace(str, i);
|
||||
@ -3850,12 +3889,12 @@ public class DecimalFormat extends NumberFormat {
|
||||
public boolean isDecimalSeparatorAlwaysShown() {
|
||||
return decimalSeparatorAlwaysShown;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When decimal match is not required, the input does not have to
|
||||
* contain a decimal mark when there is a decimal mark specified in the
|
||||
* pattern.
|
||||
* @param value true if input must contain a match to decimal mark in pattern
|
||||
* pattern.
|
||||
* @param value true if input must contain a match to decimal mark in pattern
|
||||
* Default is false.
|
||||
* @stable ICU 54
|
||||
*/
|
||||
@ -4206,19 +4245,20 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
// Here is where FieldPosition could be set for CURRENCY PLURAL.
|
||||
buffer.append(s);
|
||||
continue;
|
||||
break;
|
||||
case PATTERN_PERCENT:
|
||||
c = symbols.getPercent();
|
||||
buffer.append(symbols.getPercentString());
|
||||
break;
|
||||
case PATTERN_PER_MILLE:
|
||||
c = symbols.getPerMill();
|
||||
buffer.append(symbols.getPerMillString());
|
||||
break;
|
||||
case PATTERN_MINUS_SIGN:
|
||||
buffer.append(symbols.getMinusSignString());
|
||||
break;
|
||||
default:
|
||||
buffer.append(c);
|
||||
break;
|
||||
case PATTERN_MINUS:
|
||||
String minusString = symbols.getMinusString();
|
||||
buffer.append(minusString);
|
||||
continue;
|
||||
}
|
||||
buffer.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4263,23 +4303,22 @@ public class DecimalFormat extends NumberFormat {
|
||||
int offset = affix.indexOf(symbols.getCurrencySymbol());
|
||||
if (offset > -1) {
|
||||
formatAffix2Attribute(isPrefix, Field.CURRENCY, buf, offset,
|
||||
symbols.getCurrencySymbol().length());
|
||||
symbols.getCurrencySymbol().length());
|
||||
}
|
||||
offset = affix.indexOf(symbols.getMinusString());
|
||||
offset = affix.indexOf(symbols.getMinusSignString());
|
||||
if (offset > -1) {
|
||||
formatAffix2Attribute(isPrefix, Field.SIGN, buf, offset,
|
||||
symbols.getMinusString().length());
|
||||
formatAffix2Attribute(isPrefix, Field.SIGN, buf, offset,
|
||||
symbols.getMinusSignString().length());
|
||||
}
|
||||
// TODO: Consider if Percent and Permille can be more than one character.
|
||||
offset = affix.indexOf(symbols.getPercent());
|
||||
offset = affix.indexOf(symbols.getPercentString());
|
||||
if (offset > -1) {
|
||||
formatAffix2Attribute(isPrefix, Field.PERCENT, buf, offset,
|
||||
1);
|
||||
formatAffix2Attribute(isPrefix, Field.PERCENT, buf, offset,
|
||||
symbols.getPercentString().length());
|
||||
}
|
||||
offset = affix.indexOf(symbols.getPerMill());
|
||||
offset = affix.indexOf(symbols.getPerMillString());
|
||||
if (offset > -1) {
|
||||
formatAffix2Attribute(isPrefix, Field.PERMILLE, buf, offset,
|
||||
1);
|
||||
formatAffix2Attribute(isPrefix, Field.PERMILLE, buf, offset,
|
||||
symbols.getPerMillString().length());
|
||||
}
|
||||
offset = pattern.indexOf("¤¤¤");
|
||||
if (offset > -1) {
|
||||
@ -4290,7 +4329,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
|
||||
// Look for SIGN, PERCENT, PERMILLE in the formatted affix.
|
||||
if (fieldPosition.getFieldAttribute() == NumberFormat.Field.SIGN) {
|
||||
String sign = isNegative ? symbols.getMinusString() : symbols.getPlusString();
|
||||
String sign = isNegative ? symbols.getMinusSignString() : symbols.getPlusSignString();
|
||||
int firstPos = affix.indexOf(sign);
|
||||
if (firstPos > -1) {
|
||||
int startPos = buf.length() + firstPos;
|
||||
@ -4298,18 +4337,18 @@ public class DecimalFormat extends NumberFormat {
|
||||
fieldPosition.setEndIndex(startPos + sign.length());
|
||||
}
|
||||
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERCENT) {
|
||||
int firstPos = affix.indexOf(symbols.getPercent());
|
||||
int firstPos = affix.indexOf(symbols.getPercentString());
|
||||
if (firstPos > -1) {
|
||||
int startPos = buf.length() + firstPos;
|
||||
fieldPosition.setBeginIndex(startPos);
|
||||
fieldPosition.setEndIndex(startPos + 1);
|
||||
fieldPosition.setEndIndex(startPos + symbols.getPercentString().length());
|
||||
}
|
||||
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERMILLE) {
|
||||
int firstPos = affix.indexOf(symbols.getPerMill());
|
||||
int firstPos = affix.indexOf(symbols.getPerMillString());
|
||||
if (firstPos > -1) {
|
||||
int startPos = buf.length() + firstPos;
|
||||
fieldPosition.setBeginIndex(startPos);
|
||||
fieldPosition.setEndIndex(startPos + 1);
|
||||
fieldPosition.setEndIndex(startPos + symbols.getPerMillString().length());
|
||||
}
|
||||
} else
|
||||
// If CurrencySymbol or InternationalCurrencySymbol is in the affix, check for currency symbol.
|
||||
@ -4410,6 +4449,8 @@ public class DecimalFormat extends NumberFormat {
|
||||
|
||||
/**
|
||||
* Appends an affix pattern to the given StringBuffer. Localize unquoted specials.
|
||||
* <p>
|
||||
* <b>Note:</b> This implementation does not support new String localized symbols.
|
||||
*/
|
||||
private void appendAffixPattern(StringBuffer buffer, boolean isNegative, boolean isPrefix,
|
||||
boolean localized) {
|
||||
@ -4462,7 +4503,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
case PATTERN_PERCENT:
|
||||
ch = symbols.getPercent();
|
||||
break;
|
||||
case PATTERN_MINUS:
|
||||
case PATTERN_MINUS_SIGN:
|
||||
ch = symbols.getMinusSign();
|
||||
break;
|
||||
}
|
||||
@ -4480,6 +4521,8 @@ public class DecimalFormat extends NumberFormat {
|
||||
|
||||
/**
|
||||
* Does the real work of generating a pattern.
|
||||
* <p>
|
||||
* <b>Note:</b> This implementation does not support new String localized symbols.
|
||||
*/
|
||||
private String toPattern(boolean localized) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
@ -4619,7 +4662,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
if (part == 0) {
|
||||
if (negativeSuffix.equals(positiveSuffix) &&
|
||||
negativePrefix.equals(PATTERN_MINUS + positivePrefix)) {
|
||||
negativePrefix.equals(PATTERN_MINUS_SIGN + positivePrefix)) {
|
||||
break;
|
||||
} else {
|
||||
result.append(localized ? symbols.getPatternSeparator() : PATTERN_SEPARATOR);
|
||||
@ -4711,7 +4754,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
String exponent = String.valueOf(PATTERN_EXPONENT);
|
||||
char plus = PATTERN_PLUS_SIGN;
|
||||
char padEscape = PATTERN_PAD_ESCAPE;
|
||||
char minus = PATTERN_MINUS; // Bug 4212072 [Richard/GCL]
|
||||
char minus = PATTERN_MINUS_SIGN; // Bug 4212072 [Richard/GCL]
|
||||
if (localized) {
|
||||
zeroDigit = symbols.getZeroDigit();
|
||||
sigDigit = symbols.getSignificantDigit();
|
||||
@ -4973,7 +5016,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
// Fall through to append(ch)
|
||||
} else if (ch == minus) {
|
||||
// Convert to non-localized pattern
|
||||
ch = PATTERN_MINUS;
|
||||
ch = PATTERN_MINUS_SIGN;
|
||||
// Fall through to append(ch)
|
||||
} else if (ch == padEscape) {
|
||||
if (padPos >= 0) {
|
||||
@ -5167,7 +5210,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
(negPrefixPattern.equals(posPrefixPattern)
|
||||
&& negSuffixPattern.equals(posSuffixPattern))) {
|
||||
negSuffixPattern = posSuffixPattern;
|
||||
negPrefixPattern = PATTERN_MINUS + posPrefixPattern;
|
||||
negPrefixPattern = PATTERN_MINUS_SIGN + posPrefixPattern;
|
||||
}
|
||||
setLocale(null, null);
|
||||
// save the pattern
|
||||
@ -5254,8 +5297,8 @@ public class DecimalFormat extends NumberFormat {
|
||||
/**
|
||||
* {@icu} Sets the minimum number of significant digits that will be displayed. If
|
||||
* <code>min</code> is less than one then it is set to one. If the maximum significant
|
||||
* digits count is less than <code>min</code>, then it is set to <code>min</code>.
|
||||
* This function also enables the use of significant digits by this formatter -
|
||||
* digits count is less than <code>min</code>, then it is set to <code>min</code>.
|
||||
* This function also enables the use of significant digits by this formatter -
|
||||
* {@link #areSignificantDigitsUsed()} will return true.
|
||||
*
|
||||
* @param min the fewest significant digits to be shown
|
||||
@ -5276,7 +5319,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* {@icu} Sets the maximum number of significant digits that will be displayed. If
|
||||
* <code>max</code> is less than one then it is set to one. If the minimum significant
|
||||
* digits count is greater than <code>max</code>, then it is set to <code>max</code>.
|
||||
* This function also enables the use of significant digits by this formatter -
|
||||
* This function also enables the use of significant digits by this formatter -
|
||||
* {@link #areSignificantDigitsUsed()} will return true.
|
||||
*
|
||||
* @param max the most significant digits to be shown
|
||||
@ -5353,12 +5396,12 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the <tt>Currency Usage</tt> object used to display currency.
|
||||
* This takes effect immediately, if this format is a
|
||||
* currency format.
|
||||
* @param newUsage new currency context object to use.
|
||||
* currency format.
|
||||
* @param newUsage new currency context object to use.
|
||||
* @stable ICU 54
|
||||
*/
|
||||
public void setCurrencyUsage(CurrencyUsage newUsage) {
|
||||
@ -5384,7 +5427,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
public CurrencyUsage getCurrencyUsage() {
|
||||
return currencyUsage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the currency in effect for this formatter. Subclasses should override this
|
||||
* method as needed. Unlike getCurrency(), this method should never return null.
|
||||
@ -5456,9 +5499,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
public boolean isParseBigDecimal() {
|
||||
return parseBigDecimal;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the maximum number of exponent digits when parsing a number.
|
||||
* Set the maximum number of exponent digits when parsing a number.
|
||||
* If the limit is set too high, an OutOfMemoryException may be triggered.
|
||||
* The default value is 1000.
|
||||
* @param newValue the new limit
|
||||
@ -5469,7 +5512,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
PARSE_MAX_EXPONENT = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current maximum number of exponent digits when parsing a
|
||||
* number.
|
||||
@ -5856,7 +5899,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @since ICU 54
|
||||
*/
|
||||
private CurrencyUsage currencyUsage = CurrencyUsage.STANDARD;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
static final int currentSerialVersion = 4;
|
||||
@ -5878,7 +5921,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* <li><b>3</b>: ICU 2.2. Adds currency object.
|
||||
*
|
||||
* <li><b>4</b>: ICU 54. Adds currency usage(standard vs cash)
|
||||
*
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @serial
|
||||
@ -5958,15 +6001,12 @@ public class DecimalFormat extends NumberFormat {
|
||||
static final char PATTERN_SIGNIFICANT_DIGIT = '@';
|
||||
static final char PATTERN_EXPONENT = 'E';
|
||||
static final char PATTERN_PLUS_SIGN = '+';
|
||||
static final char PATTERN_MINUS_SIGN = '-';
|
||||
|
||||
// Affix
|
||||
private static final char PATTERN_PER_MILLE = '\u2030';
|
||||
private static final char PATTERN_PERCENT = '%';
|
||||
static final char PATTERN_PAD_ESCAPE = '*';
|
||||
/**
|
||||
* Bug 4212072 To meet the need of expandAffix(String, StirngBuffer) [Richard/GCL]
|
||||
*/
|
||||
private static final char PATTERN_MINUS = '-';
|
||||
|
||||
// Other
|
||||
private static final char PATTERN_SEPARATOR = ';';
|
||||
@ -6176,7 +6216,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* based on rounding mode and width of fractional digits. Whenever setting affecting
|
||||
* rounding mode, rounding increment and maximum width of fractional digits, then
|
||||
* this method must be called.
|
||||
*
|
||||
*
|
||||
* roundingIncrementICU is the field storing the custom rounding increment value,
|
||||
* while actual rounding increment could be larger.
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,6 @@ import com.ibm.icu.impl.CacheBase;
|
||||
import com.ibm.icu.impl.ICUData;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.SoftCache;
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.util.ULocale.Category;
|
||||
import com.ibm.icu.util.UResourceBundle;
|
||||
@ -27,7 +26,7 @@ import com.ibm.icu.util.UResourceBundleIterator;
|
||||
/**
|
||||
* <code>NumberingSystem</code> is the base class for all number
|
||||
* systems. This class provides the interface for setting different numbering
|
||||
* system types, whether it be a simple alternate digit system such as
|
||||
* system types, whether it be a simple alternate digit system such as
|
||||
* Thai digits or Devanagari digits, or an algorithmic numbering system such
|
||||
* as Hebrew numbering or Chinese numbering.
|
||||
*
|
||||
@ -51,7 +50,7 @@ public class NumberingSystem {
|
||||
|
||||
/**
|
||||
* Factory method for creating a numbering system.
|
||||
* @param radix_in The radix for this numbering system. ICU currently
|
||||
* @param radix_in The radix for this numbering system. ICU currently
|
||||
* supports only numbering systems whose radix is 10.
|
||||
* @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
|
||||
* (true) or numeric (false).
|
||||
@ -66,11 +65,11 @@ public class NumberingSystem {
|
||||
public static NumberingSystem getInstance(int radix_in, boolean isAlgorithmic_in, String desc_in ) {
|
||||
return getInstance(null,radix_in,isAlgorithmic_in,desc_in);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory method for creating a numbering system.
|
||||
* @param name_in The string representing the name of the numbering system.
|
||||
* @param radix_in The radix for this numbering system. ICU currently
|
||||
* @param radix_in The radix for this numbering system. ICU currently
|
||||
* supports only numbering systems whose radix is 10.
|
||||
* @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
|
||||
* (true) or numeric (false).
|
||||
@ -82,7 +81,7 @@ public class NumberingSystem {
|
||||
* this numbering system.
|
||||
* @stable ICU 4.6
|
||||
*/
|
||||
|
||||
|
||||
private static NumberingSystem getInstance(String name_in, int radix_in, boolean isAlgorithmic_in, String desc_in ) {
|
||||
if ( radix_in < 2 ) {
|
||||
throw new IllegalArgumentException("Invalid radix for numbering system");
|
||||
@ -252,7 +251,7 @@ public class NumberingSystem {
|
||||
* @stable ICU 4.2
|
||||
*/
|
||||
public static String [] getAvailableNames() {
|
||||
|
||||
|
||||
UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "numberingSystems");
|
||||
UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
|
||||
UResourceBundle temp;
|
||||
@ -269,29 +268,14 @@ public class NumberingSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to determine if a given digit string is valid for use as a
|
||||
* Convenience method to determine if a given digit string is valid for use as a
|
||||
* descriptor of a numeric ( non-algorithmic ) numbering system. In order for
|
||||
* a digit string to be valid, it must meet the following criteria:
|
||||
* 1. Digits must be in Unicode's basic multilingual plane.
|
||||
* a digit string to be valid, it must contain exactly ten Unicode code points.
|
||||
* @stable ICU 4.2
|
||||
*/
|
||||
public static boolean isValidDigitString(String str) {
|
||||
|
||||
int c;
|
||||
int i = 0;
|
||||
UCharacterIterator it = UCharacterIterator.getInstance(str);
|
||||
|
||||
it.setToStart();
|
||||
while ( (c = it.nextCodePoint()) != UCharacterIterator.DONE) {
|
||||
if ( UCharacter.isSupplementary(c)) { // Digits outside the BMP are not currently supported
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if ( i != 10 ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
int numCodepoints = str.codePointCount(0, str.length());
|
||||
return (numCodepoints == 10);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,7 +311,7 @@ public class NumberingSystem {
|
||||
* Returns the numbering system's algorithmic status. If true,
|
||||
* the numbering system is algorithmic and uses an RBNF formatter to
|
||||
* format numerals. If false, the numbering system is numeric and
|
||||
* uses a fixed set of digits.
|
||||
* uses a fixed set of digits.
|
||||
* @stable ICU 4.2
|
||||
*/
|
||||
public boolean isAlgorithmic() {
|
||||
|
@ -177,8 +177,8 @@ public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvid
|
||||
crb = crb.at(2);
|
||||
if (crb != null) {
|
||||
String pattern = crb.getString(0);
|
||||
char separator = crb.getString(1).charAt(0);
|
||||
char groupingSeparator = crb.getString(2).charAt(0);
|
||||
String separator = crb.getString(1);
|
||||
String groupingSeparator = crb.getString(2);
|
||||
return new CurrencyFormatInfo(pattern, separator, groupingSeparator);
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,11 @@
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**/
|
||||
|
||||
/**
|
||||
/**
|
||||
* Port From: JDK 1.4b1 : java.text.Format.IntlTestDecimalFormatSymbols
|
||||
* Source File: java/text/format/IntlTestDecimalFormatSymbols.java
|
||||
**/
|
||||
|
||||
|
||||
/*
|
||||
@test 1.4 98/03/06
|
||||
@summary test International Decimal Format Symbols
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
package com.ibm.icu.dev.test.format;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.Test;
|
||||
@ -42,7 +43,7 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
}
|
||||
|
||||
// just do some VERY basic tests to make sure that get/set work
|
||||
|
||||
|
||||
if(!en.getLocale().equals(Locale.ENGLISH)) {
|
||||
errln("ERROR: getLocale failed");
|
||||
}
|
||||
@ -63,8 +64,14 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
errln("ERROR: get/set ZeroDigit failed");
|
||||
}
|
||||
|
||||
String[] digits = en.getDigitStrings();
|
||||
fr.setDigitStrings(digits);
|
||||
if (!Arrays.equals(fr.getDigitStrings(), en.getDigitStrings())) {
|
||||
errln("ERROR: get/set DigitStrings failed");
|
||||
}
|
||||
|
||||
char sigDigit = en.getSignificantDigit();
|
||||
fr.setSignificantDigit(sigDigit);
|
||||
fr.setSignificantDigit(sigDigit);
|
||||
if(fr.getSignificantDigit() != en.getSignificantDigit()) {
|
||||
errln("ERROR: get/set SignificantDigit failed");
|
||||
}
|
||||
@ -74,47 +81,83 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
if (!fr.getCurrency().equals(currency)){
|
||||
errln("ERROR: get/set Currency failed");
|
||||
}
|
||||
|
||||
|
||||
char group = en.getGroupingSeparator();
|
||||
fr.setGroupingSeparator(group);
|
||||
if(fr.getGroupingSeparator() != en.getGroupingSeparator()) {
|
||||
errln("ERROR: get/set GroupingSeparator failed");
|
||||
}
|
||||
|
||||
String groupStr = en.getGroupingSeparatorString();
|
||||
fr.setGroupingSeparatorString(groupStr);
|
||||
if (!fr.getGroupingSeparatorString().equals(en.getGroupingSeparatorString())) {
|
||||
errln("ERROR: get/set GroupingSeparatorString failed");
|
||||
}
|
||||
|
||||
char decimal = en.getDecimalSeparator();
|
||||
fr.setDecimalSeparator(decimal);
|
||||
if(fr.getDecimalSeparator() != en.getDecimalSeparator()) {
|
||||
errln("ERROR: get/set DecimalSeparator failed");
|
||||
}
|
||||
|
||||
String decimalStr = en.getDecimalSeparatorString();
|
||||
fr.setDecimalSeparatorString(decimalStr);
|
||||
if (!fr.getDecimalSeparatorString().equals(en.getDecimalSeparatorString())) {
|
||||
errln("ERROR: get/set DecimalSeparatorString failed");
|
||||
}
|
||||
|
||||
char monetaryGroup = en.getMonetaryGroupingSeparator();
|
||||
fr.setMonetaryGroupingSeparator(monetaryGroup);
|
||||
if(fr.getMonetaryGroupingSeparator() != en.getMonetaryGroupingSeparator()) {
|
||||
errln("ERROR: get/set MonetaryGroupingSeparator failed");
|
||||
}
|
||||
|
||||
String monetaryGroupStr = en.getMonetaryGroupingSeparatorString();
|
||||
fr.setMonetaryGroupingSeparatorString(monetaryGroupStr);
|
||||
if (!fr.getMonetaryGroupingSeparatorString().equals(en.getMonetaryGroupingSeparatorString())){
|
||||
errln("ERROR: get/set MonetaryGroupingSeparatorString failed");
|
||||
}
|
||||
|
||||
char monetaryDecimal = en.getMonetaryDecimalSeparator();
|
||||
fr.setMonetaryDecimalSeparator(monetaryDecimal);
|
||||
if(fr.getMonetaryDecimalSeparator() != en.getMonetaryDecimalSeparator()) {
|
||||
errln("ERROR: get/set MonetaryDecimalSeparator failed");
|
||||
}
|
||||
|
||||
String monetaryDecimalStr = en.getMonetaryDecimalSeparatorString();
|
||||
fr.setMonetaryDecimalSeparatorString(monetaryDecimalStr);
|
||||
if (!fr.getMonetaryDecimalSeparatorString().equals(en.getMonetaryDecimalSeparatorString())) {
|
||||
errln("ERROR: get/set MonetaryDecimalSeparatorString failed");
|
||||
}
|
||||
|
||||
char perMill = en.getPerMill();
|
||||
fr.setPerMill(perMill);
|
||||
if(fr.getPerMill() != en.getPerMill()) {
|
||||
errln("ERROR: get/set PerMill failed");
|
||||
}
|
||||
|
||||
String perMillStr = en.getPerMillString();
|
||||
fr.setPerMillString(perMillStr);
|
||||
if (!fr.getPerMillString().equals(en.getPerMillString())) {
|
||||
errln("ERROR: get/set PerMillString failed");
|
||||
}
|
||||
|
||||
char percent = en.getPercent();
|
||||
fr.setPercent(percent);
|
||||
if(fr.getPercent() != en.getPercent()) {
|
||||
errln("ERROR: get/set Percent failed");
|
||||
}
|
||||
|
||||
String percentStr = en.getPercentString();
|
||||
fr.setPercentString(percentStr);
|
||||
if (!fr.getPercentString().equals(en.getPercentString())) {
|
||||
errln("ERROR: get/set PercentString failed");
|
||||
}
|
||||
|
||||
char digit = en.getDigit();
|
||||
fr.setDigit(digit);
|
||||
if(fr.getPercent() != en.getPercent()) {
|
||||
errln("ERROR: get/set Percent failed");
|
||||
if(fr.getDigit() != en.getDigit()) {
|
||||
errln("ERROR: get/set Digit failed");
|
||||
}
|
||||
|
||||
char patternSeparator = en.getPatternSeparator();
|
||||
@ -143,12 +186,24 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
errln("ERROR: get/set MinusSign failed");
|
||||
}
|
||||
|
||||
String minusSignStr = en.getMinusSignString();
|
||||
fr.setMinusSignString(minusSignStr);
|
||||
if (!fr.getMinusSignString().equals(en.getMinusSignString())) {
|
||||
errln("ERROR: get/set MinusSignString failed");
|
||||
}
|
||||
|
||||
char plusSign = en.getPlusSign();
|
||||
fr.setPlusSign(plusSign);
|
||||
if(fr.getPlusSign() != en.getPlusSign()) {
|
||||
errln("ERROR: get/set PlusSign failed");
|
||||
}
|
||||
|
||||
String plusSignStr = en.getPlusSignString();
|
||||
fr.setPlusSignString(plusSignStr);
|
||||
if (!fr.getPlusSignString().equals(en.getPlusSignString())) {
|
||||
errln("ERROR: get/set PlusSignString failed");
|
||||
}
|
||||
|
||||
char padEscape = en.getPadEscape();
|
||||
fr.setPadEscape(padEscape);
|
||||
if(fr.getPadEscape() != en.getPadEscape()) {
|
||||
@ -160,15 +215,15 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
if(fr.getExponentSeparator() != en.getExponentSeparator()) {
|
||||
errln("ERROR: get/set Exponential failed");
|
||||
}
|
||||
|
||||
|
||||
String exponentMultiplicationSign = en.getExponentMultiplicationSign();
|
||||
fr.setExponentMultiplicationSign(exponentMultiplicationSign);
|
||||
if(fr.getExponentMultiplicationSign() != en.getExponentMultiplicationSign()) {
|
||||
errln("ERROR: get/set ExponentMultiplicationSign failed");
|
||||
}
|
||||
|
||||
|
||||
// Test CurrencySpacing.
|
||||
// In CLDR 1.7, only root.txt has CurrencySpacing data. This data might
|
||||
// In CLDR 1.7, only root.txt has CurrencySpacing data. This data might
|
||||
// be different between en and fr in the future.
|
||||
for (int i = DecimalFormatSymbols.CURRENCY_SPC_CURRENCY_MATCH; i <= DecimalFormatSymbols.CURRENCY_SPC_INSERT; i++) {
|
||||
if (en.getPatternForCurrencySpacing(i, true) !=
|
||||
@ -180,7 +235,7 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String dash = "-";
|
||||
en.setPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_INSERT, true, dash);
|
||||
if (dash != en.getPatternForCurrencySpacing(DecimalFormatSymbols.CURRENCY_SPC_INSERT, true)) {
|
||||
@ -195,13 +250,43 @@ public class IntlTestDecimalFormatSymbols extends com.ibm.icu.dev.test.TestFmwk
|
||||
errln("ERROR: Clone failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCoverage() {
|
||||
DecimalFormatSymbols df = new DecimalFormatSymbols();
|
||||
DecimalFormatSymbols df2 = (DecimalFormatSymbols)df.clone();
|
||||
if (!df.equals(df2) || df.hashCode() != df2.hashCode()) {
|
||||
errln("decimal format symbols clone, equals, or hashCode failed");
|
||||
errln("decimal format symbols clone, equals, or hashCode failed");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDigitSymbols() {
|
||||
final char defZero = '0';
|
||||
final char[] defDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
final String[] defDigitStrings = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
||||
final String[] osmanyaDigitStrings = {
|
||||
"\uD801\uDCA0", "\uD801\uDCA1", "\uD801\uDCA2", "\uD801\uDCA3", "\uD801\uDCA4",
|
||||
"\uD801\uDCA5", "\uD801\uDCA6", "\uD801\uDCA7", "\uD801\uDCA8", "\uD801\uDCA9"
|
||||
};
|
||||
|
||||
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
||||
|
||||
symbols.setDigitStrings(osmanyaDigitStrings);
|
||||
if (!Arrays.equals(symbols.getDigitStrings(), osmanyaDigitStrings)) {
|
||||
errln("ERROR: Osmanya digits (supplementary) should be set");
|
||||
}
|
||||
if (defZero != symbols.getZeroDigit()) {
|
||||
errln("ERROR: Zero digit should be 0");
|
||||
}
|
||||
if (!Arrays.equals(symbols.getDigits(), defDigits)) {
|
||||
errln("ERROR: Char digits should be Latin digits");
|
||||
}
|
||||
|
||||
// Reset digits to Latin
|
||||
symbols.setZeroDigit(defZero);
|
||||
if (!Arrays.equals(symbols.getDigitStrings(), defDigitStrings)) {
|
||||
errln("ERROR: Latin digits should be set" + symbols.getDigitStrings()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +53,9 @@ import com.ibm.icu.util.CurrencyAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
public class NumberFormatTest extends TestFmwk {
|
||||
|
||||
|
||||
private static ULocale EN = new ULocale("en");
|
||||
|
||||
|
||||
private static Number toNumber(String s) {
|
||||
if (s.equals("NaN")) {
|
||||
return Double.NaN;
|
||||
@ -66,13 +66,13 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
return new BigDecimal(s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU =
|
||||
new DataDrivenNumberFormatTestUtility.CodeUnderTest() {
|
||||
@Override
|
||||
public Character Id() { return 'J'; }
|
||||
|
||||
|
||||
@Override
|
||||
public String format(NumberFormatTestData tuple) {
|
||||
DecimalFormat fmt = newDecimalFormat(tuple);
|
||||
@ -126,7 +126,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String parseCurrency(NumberFormatTestData tuple) {
|
||||
DecimalFormat fmt = newDecimalFormat(tuple);
|
||||
@ -272,12 +272,12 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
private DataDrivenNumberFormatTestUtility.CodeUnderTest JDK =
|
||||
new DataDrivenNumberFormatTestUtility.CodeUnderTest() {
|
||||
@Override
|
||||
public Character Id() { return 'K'; }
|
||||
|
||||
|
||||
@Override
|
||||
public String format(NumberFormatTestData tuple) {
|
||||
java.text.DecimalFormat fmt = newDecimalFormat(tuple);
|
||||
@ -331,8 +331,8 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param tuple
|
||||
@ -437,7 +437,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
if (tuple.localizedPattern != null) {
|
||||
fmt.applyLocalizedPattern(tuple.localizedPattern);
|
||||
}
|
||||
|
||||
|
||||
// lenient parsing not supported by JDK
|
||||
if (tuple.parseIntegerOnly != null) {
|
||||
fmt.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
|
||||
@ -455,7 +455,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
public void TestRoundingScientific10542() {
|
||||
DecimalFormat format =
|
||||
new DecimalFormat("0.00E0");
|
||||
|
||||
|
||||
int[] roundingModes = {
|
||||
BigDecimal.ROUND_CEILING,
|
||||
BigDecimal.ROUND_DOWN,
|
||||
@ -472,7 +472,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
"Round half even",
|
||||
"Round half up",
|
||||
"Round up"};
|
||||
|
||||
|
||||
double[] values = {-0.003006, -0.003005, -0.003004, 0.003014, 0.003015, 0.003016};
|
||||
// The order of these expected values correspond to the order of roundingModes and the order of values.
|
||||
String[][] expected = {
|
||||
@ -1048,22 +1048,22 @@ public class NumberFormatTest extends TestFmwk {
|
||||
// format result using CURRENCYSTYLE,
|
||||
// format result using ISOCURRENCYSTYLE,
|
||||
// format result using PLURALCURRENCYSTYLE,
|
||||
{"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
|
||||
{"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
|
||||
{"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
|
||||
{"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00美元"},
|
||||
{"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56美元"},
|
||||
{"zh_CN", "1", "CNY", "¥1.00", "CNY1.00", "1.00人民币"},
|
||||
{"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY1,234.56", "1,234.56人民币"},
|
||||
{"ru_RU", "1", "RUB", "1,00 \u20BD", "1,00 RUB", "1,00 российского рубля"},
|
||||
{"ru_RU", "2", "RUB", "2,00 \u20BD", "2,00 RUB", "2,00 российского рубля"},
|
||||
{"ru_RU", "5", "RUB", "5,00 \u20BD", "5,00 RUB", "5,00 российского рубля"},
|
||||
// test locale without currency information
|
||||
{"root", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"},
|
||||
{"root@numbers=latn", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers
|
||||
{"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
|
||||
{"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
|
||||
{"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
|
||||
{"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00美元"},
|
||||
{"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56美元"},
|
||||
{"zh_CN", "1", "CNY", "¥1.00", "CNY1.00", "1.00人民币"},
|
||||
{"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY1,234.56", "1,234.56人民币"},
|
||||
{"ru_RU", "1", "RUB", "1,00 \u20BD", "1,00 RUB", "1,00 российского рубля"},
|
||||
{"ru_RU", "2", "RUB", "2,00 \u20BD", "2,00 RUB", "2,00 российского рубля"},
|
||||
{"ru_RU", "5", "RUB", "5,00 \u20BD", "5,00 RUB", "5,00 российского рубля"},
|
||||
// test locale without currency information
|
||||
{"root", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"},
|
||||
{"root@numbers=latn", "-1.23", "USD", "-US$ 1.23", "-USD 1.23", "-1.23 USD"}, // ensure that the root locale is still used with modifiers
|
||||
{"root@numbers=arab", "-1.23", "USD", "\u200F-\u0661\u066B\u0662\u0663\u00A0US$", "\u200F-\u0661\u066B\u0662\u0663\u00A0USD", "\u200F-\u0661\u066B\u0662\u0663 USD"}, // ensure that the root locale is still used with modifiers
|
||||
{"es_AR", "1", "INR", "INR\u00A01,00", "INR\u00A01,00", "1,00 rupia india"},
|
||||
{"ar_EG", "1", "USD", "١٫٠٠\u00A0US$", "١٫٠٠\u00A0USD", "١٫٠٠ دولار أمريكي"},
|
||||
{"es_AR", "1", "INR", "INR\u00A01,00", "INR\u00A01,00", "1,00 rupia india"},
|
||||
{"ar_EG", "1", "USD", "١٫٠٠\u00A0US$", "١٫٠٠\u00A0USD", "١٫٠٠ دولار أمريكي"},
|
||||
};
|
||||
|
||||
for (int i=0; i<DATA.length; ++i) {
|
||||
@ -1287,7 +1287,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
public void TestCompatibleCurrencies() {
|
||||
NumberFormat fmt =
|
||||
NumberFormat.getCurrencyInstance(Locale.US);
|
||||
expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\u00A51,235"); // Yen half-width
|
||||
expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\u00A51,235"); // Yen half-width
|
||||
expectParseCurrency(fmt, Currency.getInstance(Locale.JAPAN), "\uFFE51,235"); // Yen full-wdith
|
||||
}
|
||||
|
||||
@ -1996,7 +1996,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Coverage tests for methods not being called otherwise.
|
||||
@Test
|
||||
public void TestNumberingSystemCoverage() {
|
||||
@ -2012,18 +2012,18 @@ public class NumberFormatTest extends TestFmwk {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!latnFound) {
|
||||
errln("ERROR: 'latn' numbering system not found on NumberingSystem.getAvailableNames().");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Test NumberingSystem.getInstance()
|
||||
NumberingSystem ns1 = NumberingSystem.getInstance();
|
||||
if (ns1 == null || ns1.isAlgorithmic()) {
|
||||
errln("ERROR: NumberingSystem.getInstance() returned a null or invalid NumberingSystem");
|
||||
}
|
||||
|
||||
|
||||
// Test NumberingSystem.getInstance(int,boolean,String)
|
||||
/* Parameters used: the ones used in the default constructor
|
||||
* radix = 10;
|
||||
@ -2034,7 +2034,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
if (ns2 == null || ns2.isAlgorithmic()) {
|
||||
errln("ERROR: NumberingSystem.getInstance(int,boolean,String) returned a null or invalid NumberingSystem");
|
||||
}
|
||||
|
||||
|
||||
// Test NumberingSystem.getInstance(Locale)
|
||||
NumberingSystem ns3 = NumberingSystem.getInstance(Locale.ENGLISH);
|
||||
if (ns3 == null || ns3.isAlgorithmic()) {
|
||||
@ -2072,6 +2072,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
this.num = inc ? 0 : 10000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (inc) {
|
||||
while (num < 10000) {
|
||||
@ -2446,19 +2447,19 @@ public class NumberFormatTest extends TestFmwk {
|
||||
double amount = 35.47;
|
||||
double negAmount = -34.567;
|
||||
FieldPosition cp = new FieldPosition(NumberFormat.Field.CURRENCY);
|
||||
|
||||
|
||||
StringBuffer buffer0 = new StringBuffer();
|
||||
nf.format(amount, buffer0, cp);
|
||||
assertEquals("$35.47", "$35.47", buffer0.toString());
|
||||
assertEquals("cp begin", 0, cp.getBeginIndex());
|
||||
assertEquals("cp end", 1, cp.getEndIndex());
|
||||
|
||||
|
||||
StringBuffer buffer01 = new StringBuffer();
|
||||
nf.format(negAmount, buffer01, cp);
|
||||
assertEquals("-$34.57", "-$34.57", buffer01.toString());
|
||||
assertEquals("cp begin", 1, cp.getBeginIndex());
|
||||
assertEquals("cp end", 2, cp.getEndIndex());
|
||||
|
||||
assertEquals("cp end", 2, cp.getEndIndex());
|
||||
|
||||
nf.setCurrency(Currency.getInstance(Locale.FRANCE));
|
||||
StringBuffer buffer1 = new StringBuffer();
|
||||
nf.format(amount, buffer1, cp);
|
||||
@ -2478,7 +2479,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("-CHF34.57", "-CHF34.57", buffer20.toString());
|
||||
assertEquals("cp begin", 1, cp.getBeginIndex());
|
||||
assertEquals("cp end", 4, cp.getEndIndex());
|
||||
|
||||
|
||||
nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.FRANCE);
|
||||
StringBuffer buffer3 = new StringBuffer();
|
||||
nf.format(amount, buffer3, cp);
|
||||
@ -2491,21 +2492,21 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("-34,57 €", "-34,57 €", buffer4.toString());
|
||||
assertEquals("cp begin", 7, cp.getBeginIndex());
|
||||
assertEquals("cp end", 8, cp.getEndIndex());
|
||||
|
||||
|
||||
nf.setCurrency(Currency.getInstance(new Locale("fr", "ch")));
|
||||
StringBuffer buffer5 = new StringBuffer();
|
||||
nf.format(negAmount, buffer5, cp);
|
||||
assertEquals("-34,57 CHF", "-34,57 CHF", buffer5.toString());
|
||||
assertEquals("cp begin", 7, cp.getBeginIndex());
|
||||
assertEquals("cp end", 10, cp.getEndIndex());
|
||||
|
||||
|
||||
NumberFormat plCurrencyFmt = NumberFormat.getInstance(new Locale("fr", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
|
||||
StringBuffer buffer6 = new StringBuffer();
|
||||
plCurrencyFmt.format(negAmount, buffer6, cp);
|
||||
assertEquals("-34.57 francs suisses", "-34.57 francs suisses", buffer6.toString());
|
||||
assertEquals("cp begin", 7, cp.getBeginIndex());
|
||||
assertEquals("cp end", 21, cp.getEndIndex());
|
||||
|
||||
assertEquals("cp end", 21, cp.getEndIndex());
|
||||
|
||||
// Positive value with PLURALCURRENCYSTYLE.
|
||||
plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
|
||||
StringBuffer buffer7 = new StringBuffer();
|
||||
@ -2513,7 +2514,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("35.47スイス フラン", "35.47スイス フラン", buffer7.toString());
|
||||
assertEquals("cp begin", 5, cp.getBeginIndex());
|
||||
assertEquals("cp end", 12, cp.getEndIndex());
|
||||
|
||||
|
||||
// PLURALCURRENCYSTYLE for non-ASCII.
|
||||
plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "de"), NumberFormat.PLURALCURRENCYSTYLE);
|
||||
StringBuffer buffer8 = new StringBuffer();
|
||||
@ -2521,7 +2522,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("-34.57ユーロ", "-34.57ユーロ", buffer8.toString());
|
||||
assertEquals("cp begin", 6, cp.getBeginIndex());
|
||||
assertEquals("cp end", 9, cp.getEndIndex());
|
||||
|
||||
|
||||
nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.JAPAN);
|
||||
nf.setCurrency(Currency.getInstance(new Locale("ja", "jp")));
|
||||
StringBuffer buffer9 = new StringBuffer();
|
||||
@ -2529,7 +2530,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("-¥35", "-¥35", buffer9.toString());
|
||||
assertEquals("cp begin", 1, cp.getBeginIndex());
|
||||
assertEquals("cp end", 2, cp.getEndIndex());
|
||||
|
||||
|
||||
// Negative value with PLURALCURRENCYSTYLE.
|
||||
plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
|
||||
StringBuffer buffer10 = new StringBuffer();
|
||||
@ -2537,7 +2538,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("-34.57スイス フラン", "-34.57スイス フラン", buffer10.toString());
|
||||
assertEquals("cp begin", 6, cp.getBeginIndex());
|
||||
assertEquals("cp end", 13, cp.getEndIndex());
|
||||
|
||||
|
||||
// Nagative value with PLURALCURRENCYSTYLE, Arabic digits.
|
||||
nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("ar", "eg"));
|
||||
plCurrencyFmt = NumberFormat.getInstance(new Locale("ar", "eg"), NumberFormat.PLURALCURRENCYSTYLE);
|
||||
@ -2547,7 +2548,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
assertEquals("cp begin", 8, cp.getBeginIndex());
|
||||
assertEquals("cp end", 17, cp.getEndIndex());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void TestRounding() {
|
||||
DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
|
||||
@ -2941,7 +2942,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
ParsePosition pos = new ParsePosition(0);
|
||||
CurrencyAmount currencyAmount = fmt.parseCurrency(text, pos);
|
||||
assertTrue("Parse of " + text + " should have succeeded.", pos.getIndex() > 0);
|
||||
assertEquals("Currency should be correct.", expected, currencyAmount.getCurrency());
|
||||
assertEquals("Currency should be correct.", expected, currencyAmount.getCurrency());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -3379,7 +3380,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
result = rbf.format(new BigDecimal(2000.43), sb, new FieldPosition(0)).toString();
|
||||
if (!"two thousand point four three".equals(result)) {
|
||||
errln("DecimalFormat failed. Expected: 'two thousand point four three' - Actual: '" + result + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3900,6 +3901,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
AttributedCharacterIterator acitr = fmt.formatToCharacterIterator(num);
|
||||
@ -4001,7 +4003,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
": ArithmeticException must be thrown, but got formatted result: " +
|
||||
s);
|
||||
} else {
|
||||
assertEquals("Test case #" + testNum, (String)testCase[5], s);
|
||||
assertEquals("Test case #" + testNum, testCase[5], s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4067,7 +4069,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
|
||||
numberFormat.setSignificantDigitsUsed(false);
|
||||
numberFormat.setMaximumSignificantDigits(6);
|
||||
assertTrue("", numberFormat.areSignificantDigitsUsed());
|
||||
assertTrue("", numberFormat.areSignificantDigitsUsed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -4177,7 +4179,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
new SignsAndMarksItem("en@numbers=arabext", false, "\u200E-\u200E\u06F6\u06F7", -67 ),
|
||||
new SignsAndMarksItem("en@numbers=arabext", true, "\u200E-\u200E\u06F6\u06F7", -67 ),
|
||||
new SignsAndMarksItem("en@numbers=arabext", true, "\u200E-\u200E \u06F6\u06F7", -67 ), // ***
|
||||
|
||||
|
||||
new SignsAndMarksItem("he", false, "12", 12 ),
|
||||
new SignsAndMarksItem("he", true, "12", 12 ),
|
||||
new SignsAndMarksItem("he", false, "-23", -23 ),
|
||||
@ -4298,7 +4300,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
expect(fmtAccount, num, fmtAccountExpected, rt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void TestCurrencyUsage() {
|
||||
// the 1st one is checking setter/getter, while the 2nd one checks for getInstance
|
||||
@ -4379,41 +4381,41 @@ public class NumberFormatTest extends TestFmwk {
|
||||
|
||||
@Test
|
||||
public void TestParseRequiredDecimalPoint() {
|
||||
|
||||
|
||||
String[] testPattern = { "00.####", "00.0", "00" };
|
||||
|
||||
|
||||
String value2Parse = "99";
|
||||
double parseValue = 99;
|
||||
DecimalFormat parser = new DecimalFormat();
|
||||
double result;
|
||||
boolean hasDecimalPoint;
|
||||
for (int i = 0; i < testPattern.length; i++) {
|
||||
boolean hasDecimalPoint;
|
||||
for (int i = 0; i < testPattern.length; i++) {
|
||||
parser.applyPattern(testPattern[i]);
|
||||
hasDecimalPoint = testPattern[i].contains(".");
|
||||
|
||||
|
||||
parser.setDecimalPatternMatchRequired(false);
|
||||
try {
|
||||
result = parser.parse(value2Parse).doubleValue();
|
||||
assertEquals("wrong parsed value", parseValue, result);
|
||||
} catch (ParseException e) {
|
||||
TestFmwk.errln("Parsing " + value2Parse + " should have succeeded with " + testPattern[i] +
|
||||
TestFmwk.errln("Parsing " + value2Parse + " should have succeeded with " + testPattern[i] +
|
||||
" and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired());
|
||||
}
|
||||
|
||||
|
||||
parser.setDecimalPatternMatchRequired(true);
|
||||
try {
|
||||
result = parser.parse(value2Parse).doubleValue();
|
||||
if(hasDecimalPoint){
|
||||
TestFmwk.errln("Parsing " + value2Parse + " should NOT have succeeded with " + testPattern[i] +
|
||||
TestFmwk.errln("Parsing " + value2Parse + " should NOT have succeeded with " + testPattern[i] +
|
||||
" and isDecimalPointMatchRequired set to: " + parser.isDecimalPatternMatchRequired());
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
// OK, should fail
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//TODO(junit): investigate
|
||||
@Test
|
||||
@ -4457,7 +4459,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
|
||||
// For each test, add assert that all the fields are present and in the right spot.
|
||||
// TODO: Add tests for identify and position of each field, as in IntlTestDecimalFormatAPIC.
|
||||
|
||||
|
||||
DecimalFormat dfDE = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.GERMANY);
|
||||
String strDE = dfDE.format(number);
|
||||
Set<AttributedCharacterIterator.Attribute> resultDE = dfDE.formatToCharacterIterator(number).getAllAttributeKeys();
|
||||
@ -4511,7 +4513,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
StringBuffer result = new StringBuffer("");
|
||||
df.setRoundingMode(BigDecimal.ROUND_UNNECESSARY);
|
||||
df.applyPattern("00.0#E0");
|
||||
|
||||
|
||||
try {
|
||||
df.format(99999.0, result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for double: " + result);
|
||||
@ -4539,7 +4541,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
} catch (ArithmeticException expected) {
|
||||
// The exception should be thrown, since rounding is needed.
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
result = df.format(new BigDecimal("-99999"), result, new FieldPosition(0));
|
||||
fail("Missing ArithmeticException for BigDecimal: " + result);
|
||||
@ -4885,4 +4887,18 @@ public class NumberFormatTest extends TestFmwk {
|
||||
checkFormatWithField("exponent", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.EXPONENT, 9, 11);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestStringSymbols() {
|
||||
DecimalFormatSymbols symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
|
||||
String[] customDigits = {"(0)", "(1)", "(2)", "(3)", "(4)", "(5)", "(6)", "(7)", "(8)", "(9)"};
|
||||
symbols.setDigitStrings(customDigits);
|
||||
symbols.setDecimalSeparatorString("~~");
|
||||
symbols.setGroupingSeparatorString("^^");
|
||||
|
||||
DecimalFormat fmt = new DecimalFormat("#,##0.0#", symbols);
|
||||
|
||||
expect2(fmt, 1234567.89, "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user