1 8 package com.ibm.icu.text; 9 10 import java.io.IOException ; 11 import java.io.ObjectInputStream ; 12 import java.io.ObjectOutputStream ; 13 import java.math.BigInteger ; 14 import java.text.AttributedCharacterIterator ; 15 import java.text.AttributedString ; 16 import java.text.ChoiceFormat ; 17 import java.text.FieldPosition ; 18 import java.text.Format ; 19 import java.text.ParsePosition ; 20 import java.util.ArrayList ; 21 22 import com.ibm.icu.impl.UCharacterProperty; 23 import com.ibm.icu.lang.UCharacter; 24 import com.ibm.icu.math.BigDecimal; 25 import com.ibm.icu.util.Currency; 26 import com.ibm.icu.util.CurrencyAmount; 27 import com.ibm.icu.util.ULocale; 28 29 613 public class DecimalFormat extends NumberFormat { 614 615 630 public DecimalFormat() { 631 ULocale def = ULocale.getDefault(); 633 String pattern = getPattern(def, 0); 634 this.symbols = new DecimalFormatSymbols(def); 636 setCurrency(Currency.getInstance(def)); 637 applyPattern(pattern, false); 638 } 639 640 641 658 public DecimalFormat(String pattern) { 659 ULocale def = ULocale.getDefault(); 661 this.symbols = new DecimalFormatSymbols(def); 662 setCurrency(Currency.getInstance(def)); 663 applyPattern( pattern, false ); 664 } 665 666 667 687 public DecimalFormat(String pattern, DecimalFormatSymbols symbols) { 688 this.symbols = (DecimalFormatSymbols) symbols.clone(); 690 setCurrencyForSymbols(); 691 applyPattern( pattern, false ); 692 } 693 694 697 public StringBuffer format(double number, StringBuffer result, 698 FieldPosition fieldPosition) { 699 return format(number, result, fieldPosition, false); 700 } 701 702 private StringBuffer format(double number, StringBuffer result, 705 FieldPosition fieldPosition, boolean parseAttr) 706 { 707 fieldPosition.setBeginIndex(0); 708 fieldPosition.setEndIndex(0); 709 710 if (Double.isNaN(number)) 711 { 712 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 713 fieldPosition.setBeginIndex(result.length()); 714 } 715 716 result.append(symbols.getNaN()); 717 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 726 fieldPosition.setEndIndex(result.length()); 727 } 728 729 addPadding(result, fieldPosition, 0, 0); 730 return result; 731 } 732 733 743 boolean isNegative = (number < 0.0) || (number == 0.0 && 1/number < 0.0); 744 if (isNegative) number = -number; 745 746 if (multiplier != 1) number *= multiplier; 748 749 if (roundingDouble > 0.0) { 751 double newNumber = round(number, roundingDouble, roundingDoubleReciprocal, roundingMode, isNegative); 754 if (newNumber == 0.0 && number != newNumber) isNegative = false; number = newNumber; 756 } 757 758 if (Double.isInfinite(number)) 759 { 760 int prefixLen = appendAffix(result, isNegative, true, parseAttr); 761 762 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 763 fieldPosition.setBeginIndex(result.length()); 764 } 765 766 result.append(symbols.getInfinity()); 768 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 775 fieldPosition.setEndIndex(result.length()); 776 } 777 778 int suffixLen = appendAffix(result, isNegative, false, parseAttr); 779 780 addPadding(result, fieldPosition, prefixLen, suffixLen); 781 return result; 782 } 783 784 synchronized(digitList) { 787 digitList.set(number, precision(false), 788 !useExponentialNotation && !areSignificantDigitsUsed()); 789 return subformat(result, fieldPosition, isNegative, false, 790 parseAttr); 791 } 792 } 793 794 810 private static double round(double number, double roundingInc, 811 double roundingIncReciprocal, int mode, boolean isNegative) { 812 813 double div = roundingIncReciprocal == 0.0 814 ? number / roundingInc 815 : number * roundingIncReciprocal; 816 817 819 switch (mode) { 820 case BigDecimal.ROUND_CEILING: 821 div = (isNegative ? Math.floor(div + epsilon) : Math.ceil(div - epsilon)); 822 break; 823 case BigDecimal.ROUND_FLOOR: 824 div = (isNegative ? Math.ceil(div - epsilon) : Math.floor(div + epsilon)); 825 break; 826 case BigDecimal.ROUND_DOWN: 827 div = (Math.floor(div + epsilon)); 828 break; 829 case BigDecimal.ROUND_UP: 830 div = (Math.ceil(div - epsilon)); 831 break; 832 case BigDecimal.ROUND_UNNECESSARY: 833 if (div != Math.floor(div)) { 834 throw new ArithmeticException ("Rounding necessary"); 835 } 836 return number; 837 default: 838 839 841 845 double ceil = Math.ceil(div); 846 double ceildiff = ceil - div; double floor = Math.floor(div); 848 double floordiff = div - floor; 850 856 switch (mode) { 857 case BigDecimal.ROUND_HALF_EVEN: 858 if (floordiff + epsilon < ceildiff) { 862 div = floor; 863 } else if (ceildiff + epsilon < floordiff) { 864 div = ceil; 865 } else { double testFloor = floor / 2; 867 div = (testFloor == Math.floor(testFloor)) ? floor : ceil; 868 } 869 break; 870 case BigDecimal.ROUND_HALF_DOWN: 871 div = ((floordiff <= ceildiff + epsilon) ? floor : ceil); 872 break; 873 case BigDecimal.ROUND_HALF_UP: 874 div = ((ceildiff <= floordiff + epsilon) ? ceil : floor); 875 break; 876 default: 877 throw new IllegalArgumentException ("Invalid rounding mode: " + mode); 878 } 879 } 880 number = roundingIncReciprocal == 0.0 881 ? div * roundingInc 882 : div / roundingIncReciprocal; 883 return number; 884 } 885 private static double epsilon = 0.00000000001; 886 887 890 public StringBuffer format(long number, StringBuffer result, 892 FieldPosition fieldPosition) { 893 return format(number, result, fieldPosition, false); 894 } 895 896 private StringBuffer format(long number, StringBuffer result, 897 FieldPosition fieldPosition, boolean parseAttr) 898 { 899 fieldPosition.setBeginIndex(0); 900 fieldPosition.setEndIndex(0); 901 902 if (roundingIncrementICU != null) { 906 return format(BigDecimal.valueOf(number), result, fieldPosition); 907 } 908 909 boolean isNegative = (number < 0); 910 if (isNegative) number = -number; 911 912 if (multiplier != 1) { 920 boolean tooBig = false; 921 if (number < 0) { long cutoff = Long.MIN_VALUE / multiplier; 923 tooBig = (number < cutoff); 924 } else { 925 long cutoff = Long.MAX_VALUE / multiplier; 926 tooBig = (number > cutoff); 927 } 928 if (tooBig) { 929 return format( 933 BigInteger.valueOf(isNegative ? -number : number), 934 result, fieldPosition, parseAttr); 935 } 936 } 937 938 number *= multiplier; 939 synchronized(digitList) { 940 digitList.set(number, precision(true)); 941 return subformat(result, fieldPosition, isNegative, true, parseAttr); 942 } 943 } 944 945 951 public StringBuffer format(BigInteger number, StringBuffer result, 952 FieldPosition fieldPosition) { 953 return format(number, result, fieldPosition, false); 954 } 955 956 private StringBuffer format(BigInteger number, StringBuffer result, 958 FieldPosition fieldPosition, boolean parseAttr) { 959 if (roundingIncrementICU != null) { 962 return format(new BigDecimal(number), result, fieldPosition); 963 } 964 965 if (multiplier != 1) { 966 number = number.multiply(BigInteger.valueOf(multiplier)); 967 } 968 969 synchronized(digitList) { 972 digitList.set(number, precision(true)); 973 return subformat(result, fieldPosition, number.signum() < 0, false, parseAttr); 974 } 975 } 976 977 1007 1012 public StringBuffer format(BigDecimal number, StringBuffer result, 1013 FieldPosition fieldPosition) { 1014 1020 if (multiplier != 1) { 1021 number = number.multiply(BigDecimal.valueOf(multiplier)); 1022 } 1023 1024 if (roundingIncrementICU != null) { 1025 number = number.divide(roundingIncrementICU, 0, roundingMode) 1026 .multiply(roundingIncrementICU); 1027 } 1028 1029 synchronized(digitList) { 1030 digitList.set(number, precision(false), 1031 !useExponentialNotation && !areSignificantDigitsUsed()); 1032 return subformat(result, fieldPosition, number.signum() < 0, false); 1033 } 1034 } 1035 1036 1046 private boolean isGroupingPosition(int pos) { 1047 boolean result = false; 1048 if (isGroupingUsed() && (pos > 0) && (groupingSize > 0)) { 1049 if ((groupingSize2 > 0) && (pos > groupingSize)) { 1050 result = ((pos - groupingSize) % groupingSize2) == 0; 1051 } else { 1052 result = pos % groupingSize == 0; 1053 } 1054 } 1055 return result; 1056 } 1057 1058 1063 private int precision(boolean isIntegral) { 1064 if (areSignificantDigitsUsed()) { 1065 return getMaximumSignificantDigits(); 1066 } else if (useExponentialNotation) { 1067 return getMinimumIntegerDigits() + getMaximumFractionDigits(); 1068 } else { 1069 return isIntegral ? 0 : getMaximumFractionDigits(); 1070 } 1071 } 1072 1073 1077 private StringBuffer subformat(StringBuffer result, FieldPosition fieldPosition, 1078 boolean isNegative, boolean isInteger){ 1079 return subformat(result, fieldPosition, isNegative, isInteger, false); 1080 } 1081 1082 private StringBuffer subformat(StringBuffer result, 1083 FieldPosition fieldPosition, boolean isNegative, boolean isInteger, 1084 boolean parseAttr) 1085 { 1086 1100 int i; 1101 char zero = symbols.getZeroDigit(); 1102 int zeroDelta = zero - '0'; char grouping = isCurrencyFormat ? 1104 symbols.getMonetaryGroupingSeparator() : 1105 symbols.getGroupingSeparator(); 1106 char decimal = isCurrencyFormat ? 1107 symbols.getMonetaryDecimalSeparator() : 1108 symbols.getDecimalSeparator(); 1109 boolean useSigDig = areSignificantDigitsUsed(); 1110 int maxIntDig = getMaximumIntegerDigits(); 1111 int minIntDig = getMinimumIntegerDigits(); 1112 1113 1119 if (digitList.isZero()) 1120 { 1121 digitList.decimalAt = 0; } 1123 1124 int prefixLen = appendAffix(result, isNegative, true, parseAttr); 1125 1126 if (useExponentialNotation) 1127 { 1128 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 1130 fieldPosition.setBeginIndex(result.length()); 1131 fieldPosition.setEndIndex(-1); 1132 } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 1133 fieldPosition.setBeginIndex(-1); 1134 } 1135 1136 int intBegin = result.length(); 1141 int intEnd = -1; 1142 int fracBegin = -1; 1143 1144 int minFracDig = 0; 1145 if (useSigDig) { 1146 maxIntDig = minIntDig = 1; 1147 minFracDig = getMinimumSignificantDigits() - 1; 1148 } else { 1149 minFracDig = getMinimumFractionDigits(); 1150 if (maxIntDig > MAX_SCIENTIFIC_INTEGER_DIGITS) { 1151 maxIntDig = 1; 1152 if (maxIntDig < minIntDig) { 1153 maxIntDig = minIntDig; 1154 } 1155 } 1156 if (maxIntDig > minIntDig) { 1157 minIntDig = 1; 1158 } 1159 } 1160 1161 1165 1173 int exponent = digitList.decimalAt; 1174 if (maxIntDig > 1 && maxIntDig != minIntDig) { 1175 exponent = (exponent > 0) ? (exponent - 1) / maxIntDig 1177 : (exponent / maxIntDig) - 1; 1178 exponent *= maxIntDig; 1179 } else { 1180 exponent -= (minIntDig > 0 || minFracDig > 0) 1183 ? minIntDig : 1; 1184 } 1185 1186 int minimumDigits = minIntDig + minFracDig; 1191 int integerDigits = digitList.isZero() ? minIntDig : 1194 digitList.decimalAt - exponent; 1195 int totalDigits = digitList.count; 1196 if (minimumDigits > totalDigits) totalDigits = minimumDigits; 1197 if (integerDigits > totalDigits) totalDigits = integerDigits; 1198 1199 for (i=0; i<totalDigits; ++i) 1200 { 1201 if (i == integerDigits) 1202 { 1203 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 1205 fieldPosition.setEndIndex(result.length()); 1206 } 1207 result.append(decimal); 1215 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 1227 fieldPosition.setBeginIndex(result.length()); 1228 } 1229 } 1230 result.append((i < digitList.count) ? 1231 (char)(digitList.digits[i] + zeroDelta) : 1232 zero); 1233 } 1234 1235 if (digitList.isZero() && (totalDigits ==0)) { 1237 result.append(zero); 1238 } 1239 1240 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 1242 if (fieldPosition.getEndIndex() < 0) { 1243 fieldPosition.setEndIndex(result.length()); 1244 } 1245 } else if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 1246 if (fieldPosition.getBeginIndex() < 0) { 1247 fieldPosition.setBeginIndex(result.length()); 1248 } 1249 fieldPosition.setEndIndex(result.length()); 1250 } 1251 1264 result.append(symbols.getExponentSeparator()); 1269 if (digitList.isZero()) exponent = 0; 1281 1282 boolean negativeExponent = exponent < 0; 1283 if (negativeExponent) { 1284 exponent = -exponent; 1285 result.append(symbols.getMinusSign()); 1286 } else if (exponentSignAlwaysShown) { 1296 result.append(symbols.getPlusSign()); 1297 } 1307 int expBegin = result.length(); 1308 digitList.set(exponent); 1309 { 1310 int expDig = minExponentDigits; 1311 if (useExponentialNotation && expDig < 1) { 1312 expDig = 1; 1313 } 1314 for (i=digitList.decimalAt; i<expDig; ++i) result.append(zero); 1315 } 1316 for (i=0; i<digitList.decimalAt; ++i) 1317 { 1318 result.append((i < digitList.count) ? 1319 (char)(digitList.digits[i] + zeroDelta) : zero); 1320 } 1321 } 1328 else 1329 { 1330 int intBegin = result.length(); 1332 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 1334 fieldPosition.setBeginIndex(result.length()); 1335 } 1336 1337 int sigCount = 0; 1338 int minSigDig = getMinimumSignificantDigits(); 1339 int maxSigDig = getMaximumSignificantDigits(); 1340 if (!useSigDig) { 1341 minSigDig = 0; 1342 maxSigDig = Integer.MAX_VALUE; 1343 } 1344 1345 int count = useSigDig ? 1350 Math.max(1, digitList.decimalAt) : minIntDig; 1351 if (digitList.decimalAt > 0 && count < digitList.decimalAt) { 1352 count = digitList.decimalAt; 1353 } 1354 1355 1360 int digitIndex = 0; if (count > maxIntDig && maxIntDig >= 0) { 1362 count = maxIntDig; 1363 digitIndex = digitList.decimalAt - count; 1364 } 1365 1366 int sizeBeforeIntegerPart = result.length(); 1367 for (i=count-1; i>=0; --i) 1368 { 1369 if (i < digitList.decimalAt && digitIndex < digitList.count && 1370 sigCount < maxSigDig) { 1371 byte d = digitList.digits[digitIndex++]; 1373 result.append((char)(d + zeroDelta)); 1374 ++sigCount; 1375 } 1376 else 1377 { 1378 result.append(zero); 1380 if (sigCount > 0) { 1381 ++sigCount; 1382 } 1383 } 1384 1385 if (isGroupingPosition(i)) { 1387 result.append(grouping); 1388 } 1397 } 1398 1399 if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) { 1401 fieldPosition.setEndIndex(result.length()); 1402 } 1403 1404 boolean fractionPresent = (!isInteger && digitIndex < digitList.count) || 1407 (useSigDig ? (sigCount < minSigDig) : (getMinimumFractionDigits() > 0)); 1408 1409 if (!fractionPresent && result.length() == sizeBeforeIntegerPart) 1413 result.append(zero); 1414 if (decimalSeparatorAlwaysShown || fractionPresent) 1422 { 1423 result.append(decimal); 1424 } 1432 1433 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 1435 fieldPosition.setBeginIndex(result.length()); 1436 } 1437 1438 int fracBegin = result.length(); 1440 1441 count = useSigDig ? Integer.MAX_VALUE : getMaximumFractionDigits(); 1442 if (useSigDig && (sigCount == maxSigDig || 1443 (sigCount >= minSigDig && digitIndex == digitList.count))) { 1444 count = 0; 1445 } 1446 for (i=0; i < count; ++i) { 1447 if (!useSigDig && i >= getMinimumFractionDigits() && 1455 (isInteger || digitIndex >= digitList.count)) { 1456 break; 1457 } 1458 1459 if (-1-i > (digitList.decimalAt-1)) { 1464 result.append(zero); 1465 continue; 1466 } 1467 1468 if (!isInteger && digitIndex < digitList.count) { 1471 result.append((char)(digitList.digits[digitIndex++] + zeroDelta)); 1472 } else { 1473 result.append(zero); 1474 } 1475 1476 ++sigCount; 1480 if (useSigDig && 1481 (sigCount == maxSigDig || 1482 (digitIndex == digitList.count && sigCount >= minSigDig))) { 1483 break; 1484 } 1485 } 1486 1487 if (fieldPosition.getField() == NumberFormat.FRACTION_FIELD) { 1489 fieldPosition.setEndIndex(result.length()); 1490 } 1491 } 1498 1499 int suffixLen = appendAffix(result, isNegative, false, parseAttr); 1500 1501 addPadding(result, fieldPosition, prefixLen, suffixLen); 1503 return result; 1504 } 1505 1506 private final void addPadding(StringBuffer result, FieldPosition fieldPosition, 1508 int prefixLen, int suffixLen) { 1509 if (formatWidth > 0) { 1510 int len = formatWidth - result.length(); 1511 if (len > 0) { 1512 char[] padding = new char[len]; 1513 for (int i=0; i<len; ++i) { 1514 padding[i] = pad; 1515 } 1516 switch (padPosition) { 1517 case PAD_AFTER_PREFIX: 1518 result.insert(prefixLen, padding); 1519 break; 1520 case PAD_BEFORE_PREFIX: 1521 result.insert(0, padding); 1522 break; 1523 case PAD_BEFORE_SUFFIX: 1524 result.insert(result.length() - suffixLen, padding); 1525 break; 1526 case PAD_AFTER_SUFFIX: 1527 result.append(padding); 1528 break; 1529 } 1530 if (padPosition == PAD_BEFORE_PREFIX || 1531 padPosition == PAD_AFTER_PREFIX) { 1532 fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + len); 1533 fieldPosition.setEndIndex(fieldPosition.getEndIndex() + len); 1534 } 1535 } 1536 } 1537 } 1538 1539 1559 public Number parse(String text, ParsePosition parsePosition) { 1560 return (Number ) parse(text, parsePosition, false); 1561 } 1562 1563 1582 CurrencyAmount parseCurrency(String text, ParsePosition pos) { 1583 return (CurrencyAmount) parse(text, pos, true); 1584 } 1585 1586 1598 private Object parse(String text, ParsePosition parsePosition, boolean parseCurrency) { 1599 int backup; 1600 int i = backup = parsePosition.getIndex(); 1601 1602 1604 if (formatWidth > 0 && (padPosition == PAD_BEFORE_PREFIX || 1606 padPosition == PAD_AFTER_PREFIX)) { 1607 i = skipPadding(text, i); 1608 } 1609 if (text.regionMatches(i, symbols.getNaN(), 1610 0, symbols.getNaN().length())) { 1611 i += symbols.getNaN().length(); 1612 if (formatWidth > 0 && (padPosition == PAD_BEFORE_SUFFIX || 1614 padPosition == PAD_AFTER_SUFFIX)) { 1615 i = skipPadding(text, i); 1616 } 1617 parsePosition.setIndex(i); 1618 return new Double (Double.NaN); 1619 } 1620 1621 i = backup; 1623 1624 boolean[] status = new boolean[STATUS_LENGTH]; 1625 Currency[] currency = parseCurrency ? new Currency[1] : null; 1626 if (!subparse(text, parsePosition, digitList, false, status, currency)) { 1627 parsePosition.setIndex(backup); 1628 return null; 1629 } 1630 1631 Number n = null; 1632 1633 if (status[STATUS_INFINITE]) { 1635 n = new Double (status[STATUS_POSITIVE] 1636 ? Double.POSITIVE_INFINITY 1637 : Double.NEGATIVE_INFINITY); 1638 } 1639 1640 else if (!status[STATUS_POSITIVE] && digitList.isZero()) { 1642 n = new Double (-0.0); 1643 } 1644 1645 else { 1646 int mult = multiplier; while (mult % 10 == 0) { 1650 --digitList.decimalAt; 1651 mult /= 10; 1652 } 1653 1654 if (!parseBigDecimal && mult == 1 && digitList.isIntegral()) { 1656 if (digitList.decimalAt < 12) { long l = 0; 1659 if (digitList.count > 0) { 1660 int nx = 0; 1661 while (nx < digitList.count) { 1662 l = l * 10 + (char)digitList.digits[nx++] - '0'; 1663 } 1664 while (nx++ < digitList.decimalAt) { 1665 l *= 10; 1666 } 1667 if (!status[STATUS_POSITIVE]) { 1668 l = -l; 1669 } 1670 } 1671 n = new Long (l); 1672 } else { 1673 BigInteger big = digitList.getBigInteger(status[STATUS_POSITIVE]); 1674 n = (big.bitLength() < 64) ? 1675 (Number ) new Long (big.longValue()) : (Number ) big; 1676 } 1677 } 1678 1679 else { 1681 BigDecimal big = digitList.getBigDecimalICU(status[STATUS_POSITIVE]); 1682 n = big; 1683 if (mult != 1) { 1684 n = big.divide(BigDecimal.valueOf(mult), 1685 BigDecimal.ROUND_HALF_EVEN); 1686 } 1687 } 1688 } 1689 1690 return parseCurrency ? (Object ) new CurrencyAmount(n, currency[0]) 1692 : (Object ) n; 1693 } 1694 1695 private static final int STATUS_INFINITE = 0; 1696 private static final int STATUS_POSITIVE = 1; 1697 private static final int STATUS_LENGTH = 2; 1698 1699 1716 private final boolean subparse(String text, ParsePosition parsePosition, 1717 DigitList digits, boolean isExponent, 1718 boolean status[], Currency currency[]) 1719 { 1720 int position = parsePosition.getIndex(); 1721 int oldStart = parsePosition.getIndex(); 1722 1723 if (formatWidth > 0 && padPosition == PAD_BEFORE_PREFIX) { 1725 position = skipPadding(text, position); 1726 } 1727 1728 int posMatch = compareAffix(text, position, false, true, currency); 1730 int negMatch = compareAffix(text, position, true, true, currency); 1731 if (posMatch >= 0 && negMatch >= 0) { 1732 if (posMatch > negMatch) { 1733 negMatch = -1; 1734 } else if (negMatch > posMatch) { 1735 posMatch = -1; 1736 } 1737 } 1738 if (posMatch >= 0) { 1739 position += posMatch; 1740 } else if (negMatch >= 0) { 1741 position += negMatch; 1742 } else { 1743 parsePosition.setErrorIndex(position); 1744 return false; 1745 } 1746 1747 if (formatWidth > 0 && padPosition == PAD_AFTER_PREFIX) { 1749 position = skipPadding(text, position); 1750 } 1751 1752 status[STATUS_INFINITE] = false; 1754 if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0, 1755 symbols.getInfinity().length())) 1756 { 1757 position += symbols.getInfinity().length(); 1758 status[STATUS_INFINITE] = true; 1759 } else { 1760 1767 digits.decimalAt = digits.count = 0; 1768 char zero = symbols.getZeroDigit(); 1769 char decimal = isCurrencyFormat ? 1770 symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator(); 1771 char grouping = symbols.getGroupingSeparator(); 1772 String exponentSep = symbols.getExponentSeparator(); 1773 boolean sawDecimal = false; 1774 boolean sawExponent = false; 1775 boolean sawDigit = false; 1776 int exponent = 0; int digit = 0; 1778 1779 boolean strictParse = isParseStrict(); 1781 boolean strictFail = false; boolean leadingZero = false; int lastGroup = -1; int prevGroup = -1; int gs2 = groupingSize2 == 0 ? groupingSize : groupingSize2; 1786 1787 int digitCount = 0; 1790 1791 int backup = -1; 1792 for (; position < text.length(); ++position) 1793 { 1794 char ch = text.charAt(position); 1795 1796 1807 digit = ch - zero; 1808 if (digit < 0 || digit > 9) digit = UCharacter.digit(ch, 10); 1809 1810 if (digit == 0) 1811 { 1812 if (strictParse && backup != -1) { 1814 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) || 1820 (lastGroup == -1 && position - oldStart - 1 > gs2)) { 1821 strictFail = true; 1822 break; 1823 } 1824 prevGroup = lastGroup; 1825 lastGroup = backup; 1826 } 1827 backup = -1; sawDigit = true; 1829 1830 if (digits.count == 0) 1832 { 1833 if (!sawDecimal) { 1834 if (strictParse && !isExponent) { 1835 if (leadingZero) { 1837 strictFail = true; 1838 break; 1839 } 1840 leadingZero = true; 1841 } 1842 continue; 1844 } 1845 1846 --digits.decimalAt; 1850 } 1851 else 1852 { 1853 ++digitCount; 1854 digits.append((char)(digit + '0')); 1855 } 1856 } 1857 else if (digit > 0 && digit <= 9) { 1859 if (strictParse) { 1860 if (leadingZero) { 1861 strictFail = true; 1863 break; 1864 } 1865 if (backup != -1) { 1866 if ((lastGroup != -1 && backup - lastGroup - 1 != gs2) || 1867 (lastGroup == -1 && position - oldStart - 1 > gs2)) { 1868 strictFail = true; 1869 break; 1870 } 1871 prevGroup = lastGroup; 1872 lastGroup = backup; 1873 } 1874 } 1875 1876 sawDigit = true; 1877 ++digitCount; 1878 digits.append((char)(digit + '0')); 1879 1880 backup = -1; 1882 } 1883 else if (!isExponent && ch == decimal) 1884 { 1885 if (strictParse) { 1886 if (backup != -1 || 1887 (lastGroup != -1 && position - lastGroup != groupingSize - 1)) { 1888 strictFail = true; 1889 break; 1890 } 1891 } 1892 if (isParseIntegerOnly() || sawDecimal) break; 1895 digits.decimalAt = digitCount; sawDecimal = true; 1897 leadingZero = false; } 1899 else if (!isExponent && ch == grouping && isGroupingUsed()) 1900 { 1901 if (sawDecimal) { 1902 break; 1903 } 1904 if (strictParse) { 1905 if ((!sawDigit || backup != -1)) { 1906 strictFail = true; 1908 break; 1909 } 1910 } 1911 backup = position; 1915 } 1916 else if (!isExponent && !sawExponent && 1917 text.regionMatches(position, exponentSep, 1918 0, exponentSep.length())) 1919 { 1920 boolean negExp = false; 1922 int pos = position + exponentSep.length(); 1923 if (pos < text.length()) { 1924 ch = text.charAt(pos); 1925 if (ch == symbols.getPlusSign()) { 1926 ++pos; 1927 } else if (ch == symbols.getMinusSign()) { 1928 ++pos; 1929 negExp = true; 1930 } 1931 } 1932 1933 DigitList exponentDigits = new DigitList(); 1934 exponentDigits.count = 0; 1935 while (pos < text.length()) { 1936 digit = text.charAt(pos) - zero; 1937 if (digit < 0 || digit > 9) { 1938 1944 digit = UCharacter.digit(text.charAt(pos), 10); 1945 } 1946 if (digit >= 0 && digit <= 9) { 1947 exponentDigits.append((char)(digit + '0')); 1948 ++pos; 1949 } else { 1950 break; 1951 } 1952 } 1953 1954 if (exponentDigits.count > 0) { 1955 if (strictParse) { 1957 if (backup != -1 || lastGroup != -1) { 1958 strictFail = true; 1959 break; 1960 } 1961 } 1962 1963 exponentDigits.decimalAt = exponentDigits.count; 1964 exponent = (int) exponentDigits.getLong(); 1965 if (negExp) { 1966 exponent = -exponent; 1967 } 1968 position = pos; sawExponent = true; 1970 } 1971 1972 break; } 1974 else break; 1975 } 1976 1977 if (backup != -1) position = backup; 1978 1979 if (strictParse && !sawDecimal) { 1980 if (lastGroup != -1 && position - lastGroup != groupingSize + 1) { 1981 strictFail = true; 1982 } 1983 } 1984 if (strictFail) { 1985 1990 parsePosition.setIndex(oldStart); 1991 parsePosition.setErrorIndex(position); 1992 return false; 1993 } 1994 1995 if (!sawDecimal) digits.decimalAt = digitCount; 1998 digits.decimalAt += exponent; 2000 2001 if (!sawDigit && digitCount == 0) { 2006 parsePosition.setIndex(oldStart); 2007 parsePosition.setErrorIndex(oldStart); 2008 return false; 2009 } 2010 } 2011 2012 if (formatWidth > 0 && padPosition == PAD_BEFORE_SUFFIX) { 2014 position = skipPadding(text, position); 2015 } 2016 2017 if (posMatch >= 0) { 2019 posMatch = compareAffix(text, position, false, false, currency); 2020 } 2021 if (negMatch >= 0) { 2022 negMatch = compareAffix(text, position, true, false, currency); 2023 } 2024 if (posMatch >= 0 && negMatch >= 0) { 2025 if (posMatch > negMatch) { 2026 negMatch = -1; 2027 } else if (negMatch > posMatch) { 2028 posMatch = -1; 2029 } 2030 } 2031 2032 if ((posMatch >= 0) == (negMatch >= 0)) { 2034 parsePosition.setErrorIndex(position); 2035 return false; 2036 } 2037 2038 position += (posMatch>=0 ? posMatch : negMatch); 2039 2040 if (formatWidth > 0 && padPosition == PAD_AFTER_SUFFIX) { 2042 position = skipPadding(text, position); 2043 } 2044 2045 parsePosition.setIndex(position); 2046 2047 status[STATUS_POSITIVE] = (posMatch >= 0); 2048 2049 if (parsePosition.getIndex() == oldStart) { 2050 parsePosition.setErrorIndex(position); 2051 return false; 2052 } 2053 return true; 2054 } 2055 2056 2061 private final int skipPadding(String text, int position) { 2062 while (position < text.length() && text.charAt(position) == pad) { 2063 ++position; 2064 } 2065 return position; 2066 } 2067 2068 2083 private int compareAffix(String text, int pos, boolean isNegative, 2084 boolean isPrefix, Currency[] currency) { 2085 if (currency != null || currencyChoice != null) { 2086 if (isPrefix) { 2087 return compareComplexAffix(isNegative ? negPrefixPattern : posPrefixPattern, 2088 text, pos, currency); 2089 } else { 2090 return compareComplexAffix(isNegative ? negSuffixPattern : posSuffixPattern, 2091 text, pos, currency); 2092 } 2093 } 2094 2095 if (isPrefix) { 2096 return compareSimpleAffix(isNegative ? negativePrefix : positivePrefix, 2097 text, pos); 2098 } else { 2099 return compareSimpleAffix(isNegative ? negativeSuffix : positiveSuffix, 2100 text, pos); 2101 } 2102 } 2103 2104 2114 private static int compareSimpleAffix(String affix, String input, int pos) { 2115 int start = pos; 2116 for (int i=0; i<affix.length(); ) { 2117 int c = UTF16.charAt(affix, i); 2118 int len = UTF16.getCharCount(c); 2119 if (UCharacterProperty.isRuleWhiteSpace(c)) { 2120 boolean literalMatch = false; 2127 while (pos < input.length() && 2128 UTF16.charAt(input, pos) == c) { 2129 literalMatch = true; 2130 i += len; 2131 pos += len; 2132 if (i == affix.length()) { 2133 break; 2134 } 2135 c = UTF16.charAt(affix, i); 2136 len = UTF16.getCharCount(c); 2137 if (!UCharacterProperty.isRuleWhiteSpace(c)) { 2138 break; 2139 } 2140 } 2141 2142 i = skipRuleWhiteSpace(affix, i); 2144 2145 int s = pos; 2149 pos = skipUWhiteSpace(input, pos); 2150 if (pos == s && !literalMatch) { 2151 return -1; 2152 } 2153 } else { 2154 if (pos < input.length() && 2155 UTF16.charAt(input, pos) == c) { 2156 i += len; 2157 pos += len; 2158 } else { 2159 return -1; 2160 } 2161 } 2162 } 2163 return pos - start; 2164 } 2165 2166 2170 private static int skipRuleWhiteSpace(String text, int pos) { 2171 while (pos < text.length()) { 2172 int c = UTF16.charAt(text, pos); 2173 if (!UCharacterProperty.isRuleWhiteSpace(c)) { 2174 break; 2175 } 2176 pos += UTF16.getCharCount(c); 2177 } 2178 return pos; 2179 } 2180 2181 2185 private static int skipUWhiteSpace(String text, int pos) { 2186 while (pos < text.length()) { 2187 int c = UTF16.charAt(text, pos); 2188 if (!UCharacter.isUWhiteSpace(c)) { 2189 break; 2190 } 2191 pos += UTF16.getCharCount(c); 2192 } 2193 return pos; 2194 } 2195 2196 2207 private int compareComplexAffix(String affixPat, String text, int pos, 2208 Currency[] currency) { 2209 2210 for (int i=0; i<affixPat.length() && pos >= 0; ) { 2211 char c = affixPat.charAt(i++); 2212 if (c == QUOTE) { 2213 for (;;) { 2214 int j = affixPat.indexOf(QUOTE, i); 2215 if (j == i) { 2216 pos = match(text, pos, QUOTE); 2217 i = j+1; 2218 break; 2219 } else if (j > i) { 2220 pos = match(text, pos, affixPat.substring(i, j)); 2221 i = j+1; 2222 if (i<affixPat.length() && 2223 affixPat.charAt(i)==QUOTE) { 2224 pos = match(text, pos, QUOTE); 2225 ++i; 2226 } else { 2228 break; 2229 } 2230 } else { 2231 throw new RuntimeException (); 2234 } 2235 } 2236 continue; 2237 } 2238 2239 switch (c) { 2240 case CURRENCY_SIGN: 2241 boolean intl = i<affixPat.length() && 2246 affixPat.charAt(i) == CURRENCY_SIGN; 2247 2248 if (currency != null) { 2251 ULocale uloc = getLocale(ULocale.VALID_LOCALE); 2254 if (uloc == null) { 2255 uloc = symbols.getLocale(ULocale.VALID_LOCALE); 2257 } 2258 ParsePosition ppos = new ParsePosition (pos); 2260 String iso = Currency.parse(uloc, text, ppos); 2261 2262 if (iso != null) { 2264 currency[0] = Currency.getInstance(iso); 2265 pos = ppos.getIndex(); 2266 } else { 2267 pos = -1; 2268 } 2269 } else { 2270 if (intl) { 2271 ++i; 2272 pos = match(text, pos, getCurrency().getCurrencyCode()); 2273 } else { 2274 ParsePosition ppos = new ParsePosition (pos); 2275 currencyChoice.parse(text, ppos); 2276 pos = (ppos.getIndex() == pos) ? -1 : ppos.getIndex(); 2277 } 2278 } 2279 continue; 2280 case PATTERN_PERCENT: 2281 c = symbols.getPercent(); 2282 break; 2283 case PATTERN_PER_MILLE: 2284 c = symbols.getPerMill(); 2285 break; 2286 case PATTERN_MINUS: 2287 c = symbols.getMinusSign(); 2288 break; 2289 } 2290 pos = match(text, pos, c); 2291 if (UCharacterProperty.isRuleWhiteSpace(c)) { 2292 i = skipRuleWhiteSpace(affixPat, i); 2293 } 2294 } 2295 2296 return pos; 2297 } 2298 2299 2304 static final int match(String text, int pos, int ch) { 2305 if (UCharacterProperty.isRuleWhiteSpace(ch)) { 2306 int s = pos; 2309 pos = skipUWhiteSpace(text, pos); 2310 if (pos == s) { 2311 return -1; 2312 } 2313 return pos; 2314 } 2315 return (pos >= 0 && UTF16.charAt(text, pos) == ch) ? 2316 (pos + UTF16.getCharCount(ch)) : -1; 2317 } 2318 2319 2324 static final int match(String text, int pos, String str) { 2325 for (int i=0; i<str.length() && pos >= 0; ) { 2326 int ch = UTF16.charAt(str, i); 2327 i += UTF16.getCharCount(ch); 2328 pos = match(text, pos, ch); 2329 if (UCharacterProperty.isRuleWhiteSpace(ch)) { 2330 i = skipRuleWhiteSpace(str, i); 2331 } 2332 } 2333 return pos; 2334 } 2335 2336 2342 public DecimalFormatSymbols getDecimalFormatSymbols() { 2343 try { 2344 return (DecimalFormatSymbols) symbols.clone(); 2346 } catch (Exception foo) { 2347 return null; } 2349 } 2350 2351 2352 2359 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { 2360 symbols = (DecimalFormatSymbols) newSymbols.clone(); 2361 setCurrencyForSymbols(); 2362 expandAffixes(); 2363 } 2364 2365 2370 private void setCurrencyForSymbols() { 2371 2376 2377 DecimalFormatSymbols def = 2384 new DecimalFormatSymbols(symbols.getLocale()); 2385 2386 if (symbols.getCurrencySymbol().equals( 2387 def.getCurrencySymbol()) && 2388 symbols.getInternationalCurrencySymbol().equals( 2389 def.getInternationalCurrencySymbol())) { 2390 setCurrency(Currency.getInstance(symbols.getLocale())); 2391 } else { 2392 setCurrency(null); 2393 } 2394 } 2395 2396 2401 public String getPositivePrefix () { 2402 return positivePrefix; 2403 } 2404 2405 2410 public void setPositivePrefix (String newValue) { 2411 positivePrefix = newValue; 2412 posPrefixPattern = null; 2413 } 2414 2415 2420 public String getNegativePrefix () { 2421 return negativePrefix; 2422 } 2423 2424 2429 public void setNegativePrefix (String newValue) { 2430 negativePrefix = newValue; 2431 negPrefixPattern = null; 2432 } 2433 2434 2439 public String getPositiveSuffix () { 2440 return positiveSuffix; 2441 } 2442 2443 2448 public void setPositiveSuffix (String newValue) { 2449 positiveSuffix = newValue; 2450 posSuffixPattern = null; 2451 } 2452 2453 2458 public String getNegativeSuffix () { 2459 return negativeSuffix; 2460 } 2461 2462 2467 public void setNegativeSuffix (String newValue) { 2468 negativeSuffix = newValue; 2469 negSuffixPattern = null; 2470 } 2471 2472 2480 public int getMultiplier () { 2481 return multiplier; 2482 } 2483 2484 2492 public void setMultiplier (int newValue) { 2493 if (newValue <= 0) { 2494 throw new IllegalArgumentException ("Bad multiplier: " + newValue); 2495 } 2496 multiplier = newValue; 2497 } 2498 2499 2509 public BigDecimal getRoundingIncrement() { 2511 if (roundingIncrementICU == null) return null; 2512 return new BigDecimal(roundingIncrementICU.toString()); 2513 } 2514 2528 2550 2563 public void setRoundingIncrement(BigDecimal newValue) { 2564 int i = newValue == null 2565 ? 0 : newValue.compareTo(BigDecimal.ZERO); 2566 if (i < 0) { 2567 throw new IllegalArgumentException ("Illegal rounding increment"); 2568 } 2569 if (i == 0) { 2570 setInternalRoundingIncrement(null); 2571 } else { 2572 setInternalRoundingIncrement(newValue); 2573 } 2574 setRoundingDouble(); 2575 } 2576 2577 2578 2590 public void setRoundingIncrement(double newValue) { 2591 if (newValue < 0.0) { 2592 throw new IllegalArgumentException ("Illegal rounding increment"); 2593 } 2594 roundingDouble = newValue; 2595 roundingDoubleReciprocal = 0.0d; 2596 if (newValue == 0.0d) { 2597 setRoundingIncrement((BigDecimal)null); 2598 } else { 2599 roundingDouble = newValue; 2600 if (roundingDouble < 1.0d) { 2601 double rawRoundedReciprocal = 1.0d/roundingDouble; 2602 setRoundingDoubleReciprocal(rawRoundedReciprocal); 2603 } 2604 setInternalRoundingIncrement(new BigDecimal(newValue)); 2605 } 2606 } 2607 2608 2609 private void setRoundingDoubleReciprocal(double rawRoundedReciprocal) { 2610 roundingDoubleReciprocal = Math.rint(rawRoundedReciprocal); 2611 if (Math.abs(rawRoundedReciprocal - roundingDoubleReciprocal) > roundingIncrementEpsilon) { 2612 roundingDoubleReciprocal = 0.0d; 2613 } 2614 } 2615 2616 static final double roundingIncrementEpsilon = 0.000000001; 2617 2618 2629 public int getRoundingMode() { 2630 return roundingMode; 2631 } 2632 2633 2648 public void setRoundingMode(int roundingMode) { 2649 if (roundingMode < BigDecimal.ROUND_UP 2650 || roundingMode > BigDecimal.ROUND_UNNECESSARY) { 2651 throw new IllegalArgumentException ("Invalid rounding mode: " 2652 + roundingMode); 2653 } 2654 this.roundingMode = roundingMode; 2655 } 2656 2657 2669 public int getFormatWidth() { 2670 return formatWidth; 2671 } 2672 2673 2688 public void setFormatWidth(int width) { 2689 if (width < 0) { 2690 throw new IllegalArgumentException ("Illegal format width"); 2691 } 2692 formatWidth = width; 2693 } 2694 2695 2706 public char getPadCharacter() { 2707 return pad; 2708 } 2709 2710 2723 public void setPadCharacter(char padChar) { 2724 pad = padChar; 2725 } 2726 2727 2746 public int getPadPosition() { 2747 return padPosition; 2748 } 2749 2750 2772 public void setPadPosition(int padPos) { 2773 if (padPos < PAD_BEFORE_PREFIX || padPos > PAD_AFTER_SUFFIX) { 2774 throw new IllegalArgumentException ("Illegal pad position"); 2775 } 2776 padPosition = padPos; 2777 } 2778 2779 2790 public boolean isScientificNotation() { 2791 return useExponentialNotation; 2792 } 2793 2794 2810 public void setScientificNotation(boolean useScientific) { 2811 useExponentialNotation = useScientific; 2812 } 2813 2814 2825 public byte getMinimumExponentDigits() { 2826 return minExponentDigits; 2827 } 2828 2829 2843 public void setMinimumExponentDigits(byte minExpDig) { 2844 if (minExpDig < 1) { 2845 throw new IllegalArgumentException ("Exponent digits must be >= 1"); 2846 } 2847 minExponentDigits = minExpDig; 2848 } 2849 2850 2863 public boolean isExponentSignAlwaysShown() { 2864 return exponentSignAlwaysShown; 2865 } 2866 2867 2881 public void setExponentSignAlwaysShown(boolean expSignAlways) { 2882 exponentSignAlwaysShown = expSignAlways; 2883 } 2884 2885 2894 public int getGroupingSize () { 2895 return groupingSize; 2896 } 2897 2898 2907 public void setGroupingSize (int newValue) { 2908 groupingSize = (byte)newValue; 2909 } 2910 2911 2930 public int getSecondaryGroupingSize () { 2931 return groupingSize2; 2932 } 2933 2934 2944 public void setSecondaryGroupingSize (int newValue) { 2945 groupingSize2 = (byte)newValue; 2946 } 2947 2948 2954 public boolean isDecimalSeparatorAlwaysShown() { 2955 return decimalSeparatorAlwaysShown; 2956 } 2957 2958 2972 public void setDecimalSeparatorAlwaysShown(boolean newValue) { 2973 decimalSeparatorAlwaysShown = newValue; 2974 } 2975 2976 2980 public Object clone() { 2981 try { 2982 DecimalFormat other = (DecimalFormat) super.clone(); 2983 other.symbols = (DecimalFormatSymbols) symbols.clone(); 2984 other.digitList = new DigitList(); 2991 return other; 2992 } catch (Exception e) { 2993 throw new IllegalStateException (); 2994 } 2995 } 2996 2997 3001 public boolean equals(Object obj) 3002 { 3003 if (obj == null) return false; 3004 if (!super.equals(obj)) return false; 3006 DecimalFormat other = (DecimalFormat) obj; 3007 3011 return (posPrefixPattern != null && 3012 equals(posPrefixPattern, other.posPrefixPattern)) 3013 && (posSuffixPattern != null && 3014 equals(posSuffixPattern, other.posSuffixPattern)) 3015 && (negPrefixPattern != null && 3016 equals(negPrefixPattern, other.negPrefixPattern)) 3017 && (negSuffixPattern != null && 3018 equals(negSuffixPattern, other.negSuffixPattern)) 3019 && multiplier == other.multiplier 3020 && groupingSize == other.groupingSize 3021 && groupingSize2 == other.groupingSize2 3022 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown 3023 && useExponentialNotation == other.useExponentialNotation 3024 && (!useExponentialNotation || 3025 minExponentDigits == other.minExponentDigits) 3026 && useSignificantDigits == other.useSignificantDigits 3027 && (!useSignificantDigits || 3028 minSignificantDigits == other.minSignificantDigits && 3029 maxSignificantDigits == other.maxSignificantDigits) 3030 && symbols.equals(other.symbols); 3031 } 3032 private boolean equals(String pat1, String pat2){ 3034 if(pat1.equals(pat2)){ 3036 return true; 3037 } 3038 return unquote(pat1).equals(unquote(pat2)); 3039 } 3040 private String unquote(String pat){ 3041 StringBuffer buf = new StringBuffer (pat.length()); 3042 int i=0; 3043 while(i<pat.length()){ 3044 char ch = pat.charAt(i++); 3045 if(ch!=QUOTE){ 3046 buf.append(ch); 3047 } 3048 } 3049 return buf.toString(); 3050 } 3051 3072 3076 public int hashCode() { 3077 return super.hashCode() * 37 + positivePrefix.hashCode(); 3078 } 3080 3081 3087 public String toPattern() { 3088 return toPattern( false ); 3089 } 3090 3091 3097 public String toLocalizedPattern() { 3098 return toPattern( true ); 3099 } 3100 3101 3107 private void expandAffixes() { 3109 currencyChoice = null; 3112 3113 StringBuffer buffer = new StringBuffer (); 3115 if (posPrefixPattern != null) { 3116 expandAffix(posPrefixPattern, buffer, false); 3117 positivePrefix = buffer.toString(); 3118 } 3119 if (posSuffixPattern != null) { 3120 expandAffix(posSuffixPattern, buffer, false); 3121 positiveSuffix = buffer.toString(); 3122 } 3123 if (negPrefixPattern != null) { 3124 expandAffix(negPrefixPattern, buffer, false); 3125 negativePrefix = buffer.toString(); 3126 } 3127 if (negSuffixPattern != null) { 3128 expandAffix(negSuffixPattern, buffer, false); 3129 negativeSuffix = buffer.toString(); 3130 } 3131 } 3132 3133 3163 private void expandAffix(String pattern, StringBuffer buffer, 3165 boolean doFormat) { 3166 buffer.setLength(0); 3167 for (int i=0; i<pattern.length(); ) { 3168 char c = pattern.charAt(i++); 3169 if (c == QUOTE) { 3170 for (;;) { 3171 int j = pattern.indexOf(QUOTE, i); 3172 if (j == i) { 3173 buffer.append(QUOTE); 3174 i = j+1; 3175 break; 3176 } else if (j > i) { 3177 buffer.append(pattern.substring(i, j)); 3178 i = j+1; 3179 if (i<pattern.length() && 3180 pattern.charAt(i)==QUOTE) { 3181 buffer.append(QUOTE); 3182 ++i; 3183 } else { 3185 break; 3186 } 3187 } else { 3188 throw new RuntimeException (); 3191 } 3192 } 3193 continue; 3194 } 3195 3196 switch (c) { 3197 case CURRENCY_SIGN: 3198 boolean intl = i<pattern.length() && 3204 pattern.charAt(i) == CURRENCY_SIGN; 3205 if (intl) { 3206 ++i; 3207 } 3208 String s = null; 3209 Currency currency = getCurrency(); 3210 if (currency != null) { 3211 if (!intl) { 3212 boolean isChoiceFormat[] = new boolean[1]; 3213 s = currency.getName(symbols.getULocale(), 3214 Currency.SYMBOL_NAME, 3215 isChoiceFormat); 3216 if (isChoiceFormat[0]) { 3217 if (!doFormat) { 3222 if (currencyChoice == null) { 3227 currencyChoice = new ChoiceFormat (s); 3228 } 3229 s = String.valueOf(CURRENCY_SIGN); 3237 } else { 3238 FieldPosition pos = new FieldPosition (0); currencyChoice.format(digitList.getDouble(), buffer, pos); 3240 continue; 3241 } 3242 } 3243 } else { 3244 s = currency.getCurrencyCode(); 3245 } 3246 } else { 3247 s = intl ? symbols.getInternationalCurrencySymbol() 3248 : symbols.getCurrencySymbol(); 3249 } 3250 buffer.append(s); 3251 continue; 3252 case PATTERN_PERCENT: 3253 c = symbols.getPercent(); 3254 break; 3255 case PATTERN_PER_MILLE: 3256 c = symbols.getPerMill(); 3257 break; 3258 case PATTERN_MINUS: 3259 c = symbols.getMinusSign(); 3260 break; 3261 } 3262 buffer.append(c); 3263 } 3264 } 3265 3266 3272 private int appendAffix(StringBuffer buf, boolean isNegative, 3273 boolean isPrefix, boolean parseAttr) { 3274 if (currencyChoice != null) { 3275 String affixPat = null; 3276 if (isPrefix) { 3277 affixPat = isNegative ? negPrefixPattern : posPrefixPattern; 3278 } else { 3279 affixPat = isNegative ? negSuffixPattern : posSuffixPattern; 3280 } 3281 StringBuffer affixBuf = new StringBuffer (); 3282 expandAffix(affixPat, affixBuf, true); 3283 buf.append(affixBuf.toString()); 3284 return affixBuf.length(); 3285 } 3286 3287 String affix = null; 3288 if (isPrefix) { 3289 affix = isNegative ? negativePrefix : positivePrefix; 3290 } else { 3291 affix = isNegative ? negativeSuffix : positiveSuffix; 3292 } 3293 buf.append(affix); 3308 return affix.length(); 3309 } 3310 3311 3333 3345 3390 private void appendAffixPattern(StringBuffer buffer, 3391 boolean isNegative, boolean isPrefix, 3392 boolean localized) { 3393 String affixPat = null; 3394 if (isPrefix) { 3395 affixPat = isNegative ? negPrefixPattern : posPrefixPattern; 3396 } else { 3397 affixPat = isNegative ? negSuffixPattern : posSuffixPattern; 3398 } 3399 3400 if (affixPat == null) { 3402 String affix = null; 3403 if (isPrefix) { 3404 affix = isNegative ? negativePrefix : positivePrefix; 3405 } else { 3406 affix = isNegative ? negativeSuffix : positiveSuffix; 3407 } 3408 buffer.append(QUOTE); 3410 for (int i=0; i<affix.length(); ++i) { 3411 char ch = affix.charAt(i); 3412 if (ch == QUOTE) { 3413 buffer.append(ch); 3414 } 3415 buffer.append(ch); 3416 } 3417 buffer.append(QUOTE); 3418 return; 3419 } 3420 3421 if (!localized) { 3422 buffer.append(affixPat); 3423 } else { 3424 int i, j; 3425 for (i=0; i<affixPat.length(); ++i) { 3426 char ch = affixPat.charAt(i); 3427 switch (ch) { 3428 case QUOTE: 3429 j = affixPat.indexOf(QUOTE, i+1); 3430 if (j < 0) { 3431 throw new IllegalArgumentException ("Malformed affix pattern: " + affixPat); 3432 } 3433 buffer.append(affixPat.substring(i, j+1)); 3434 i = j; 3435 continue; 3436 case PATTERN_PER_MILLE: 3437 ch = symbols.getPerMill(); 3438 break; 3439 case PATTERN_PERCENT: 3440 ch = symbols.getPercent(); 3441 break; 3442 case PATTERN_MINUS: 3443 ch = symbols.getMinusSign(); 3444 break; 3445 } 3446 if(ch==symbols.getDecimalSeparator() || 3448 ch==symbols.getGroupingSeparator() ){ 3449 buffer.append(QUOTE); 3450 buffer.append(ch); 3451 buffer.append(QUOTE); 3452 }else{ 3453 buffer.append(ch); 3454 } 3455 } 3456 } 3457 } 3458 3459 3463 private String toPattern(boolean localized) { 3464 StringBuffer result = new StringBuffer (); 3465 char zero = localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT; 3466 char digit = localized ? symbols.getDigit() : PATTERN_DIGIT; 3467 char sigDigit = 0; 3468 boolean useSigDig = areSignificantDigitsUsed(); 3469 if (useSigDig) { 3470 sigDigit = localized ? symbols.getSignificantDigit() : PATTERN_SIGNIFICANT_DIGIT; 3471 } 3472 char group = localized ? symbols.getGroupingSeparator() 3473 : PATTERN_GROUPING_SEPARATOR; 3474 int i; 3475 int roundingDecimalPos = 0; String roundingDigits = null; 3477 int padPos = (formatWidth > 0) ? padPosition : -1; 3478 String padSpec = (formatWidth > 0) 3479 ? new StringBuffer (2). 3480 append(localized ? symbols.getPadEscape() : PATTERN_PAD_ESCAPE). 3481 append(pad).toString() 3482 : null; 3483 if (roundingIncrementICU != null) { 3484 i = roundingIncrementICU.scale(); 3485 roundingDigits = roundingIncrementICU.movePointRight(i).toString(); 3486 roundingDecimalPos = roundingDigits.length() - i; 3487 } 3488 for (int part=0; part<2; ++part) { 3489 if (padPos == PAD_BEFORE_PREFIX) { 3491 result.append(padSpec); 3492 } 3493 3496 appendAffixPattern(result, part!=0, true, localized); 3497 if (padPos == PAD_AFTER_PREFIX) { 3498 result.append(padSpec); 3499 } 3500 int sub0Start = result.length(); 3501 int g = isGroupingUsed() ? Math.max(0, groupingSize) : 0; 3502 if (g > 0 && groupingSize2 > 0 && groupingSize2 != groupingSize) { 3503 g += groupingSize2; 3504 } 3505 int maxDig = 0, minDig = 0, maxSigDig = 0; 3506 if (useSigDig) { 3507 minDig = getMinimumSignificantDigits(); 3508 maxDig = maxSigDig = getMaximumSignificantDigits(); 3509 } else { 3510 minDig = getMinimumIntegerDigits(); 3511 maxDig = getMaximumIntegerDigits(); 3512 } 3513 if (useExponentialNotation) { 3514 if (maxDig > MAX_SCIENTIFIC_INTEGER_DIGITS) { 3515 maxDig = 1; 3516 } 3517 } else if (useSigDig) { 3518 maxDig = Math.max(maxDig, g+1); 3519 } else { 3520 maxDig = Math.max(Math.max(g, getMinimumIntegerDigits()), 3521 roundingDecimalPos) + 1; 3522 } 3523 for (i = maxDig; i > 0; --i) { 3524 if (!useExponentialNotation && i<maxDig && 3525 isGroupingPosition(i)) { 3526 result.append(group); 3527 } 3528 if (useSigDig) { 3529 result.append((maxSigDig >= i && i > (maxSigDig - minDig)) ? sigDigit : digit); 3534 } else { 3535 if (roundingDigits != null) { 3536 int pos = roundingDecimalPos - i; 3537 if (pos >= 0 && pos < roundingDigits.length()) { 3538 result.append((char) (roundingDigits.charAt(pos) - '0' + zero)); 3539 continue; 3540 } 3541 } 3542 result.append(i<=minDig ? zero : digit); 3543 } 3544 } 3545 if (!useSigDig) { 3546 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) { 3547 result.append(localized ? symbols.getDecimalSeparator() : 3548 PATTERN_DECIMAL_SEPARATOR); 3549 } 3550 int pos = roundingDecimalPos; 3551 for (i = 0; i < getMaximumFractionDigits(); ++i) { 3552 if (roundingDigits != null && 3553 pos < roundingDigits.length()) { 3554 result.append(pos < 0 ? zero : 3555 (char) (roundingDigits.charAt(pos) - '0' + zero)); 3556 ++pos; 3557 continue; 3558 } 3559 result.append(i<getMinimumFractionDigits() ? zero : digit); 3560 } 3561 } 3562 if (useExponentialNotation) { 3563 if(localized ){ 3564 result.append(symbols.getExponentSeparator() ); 3565 }else{ 3566 result.append(PATTERN_EXPONENT); 3567 } 3568 if (exponentSignAlwaysShown) { 3569 result.append(localized ? symbols.getPlusSign() : 3570 PATTERN_PLUS_SIGN); 3571 } 3572 for (i=0; i<minExponentDigits; ++i) { 3573 result.append(zero); 3574 } 3575 } 3576 if (padSpec != null && !useExponentialNotation) { 3577 int add = formatWidth - result.length() + sub0Start 3578 - ((part == 0) 3579 ? positivePrefix.length() + positiveSuffix.length() 3580 : negativePrefix.length() + negativeSuffix.length()); 3581 while (add > 0) { 3582 result.insert(sub0Start, digit); 3583 ++maxDig; 3584 --add; 3585 if (add>1 && isGroupingPosition(maxDig)) { 3589 result.insert(sub0Start, group); 3590 --add; 3591 } 3592 } 3593 } 3594 if (padPos == PAD_BEFORE_SUFFIX) { 3595 result.append(padSpec); 3596 } 3597 3600 appendAffixPattern(result, part!=0, false, localized); 3601 if (padPos == PAD_AFTER_SUFFIX) { 3602 result.append(padSpec); 3603 } 3604 if (part == 0) { 3605 if (negativeSuffix.equals(positiveSuffix) && 3606 negativePrefix.equals( PATTERN_MINUS + positivePrefix)) { 3607 break; 3608 } else { 3609 result.append(localized ? symbols.getPatternSeparator() : 3610 PATTERN_SEPARATOR); 3611 } 3612 } 3613 } 3614 return result.toString(); 3615 } 3616 3617 3635 public void applyPattern( String pattern ) { 3636 applyPattern( pattern, false ); 3637 } 3638 3639 3658 public void applyLocalizedPattern( String pattern ) { 3659 applyPattern( pattern, true ); 3660 } 3661 3662 3666 private void applyPattern(String pattern, boolean localized) { 3667 char zeroDigit = PATTERN_ZERO_DIGIT; char sigDigit = PATTERN_SIGNIFICANT_DIGIT; char groupingSeparator = PATTERN_GROUPING_SEPARATOR; 3670 char decimalSeparator = PATTERN_DECIMAL_SEPARATOR; 3671 char percent = PATTERN_PERCENT; 3672 char perMill = PATTERN_PER_MILLE; 3673 char digit = PATTERN_DIGIT; char separator = PATTERN_SEPARATOR; 3675 String exponent = String.valueOf(PATTERN_EXPONENT); 3676 char plus = PATTERN_PLUS_SIGN; 3677 char padEscape = PATTERN_PAD_ESCAPE; 3678 char minus = PATTERN_MINUS; if (localized) { 3680 zeroDigit = symbols.getZeroDigit(); 3681 sigDigit = symbols.getSignificantDigit(); 3682 groupingSeparator = symbols.getGroupingSeparator(); 3683 decimalSeparator = symbols.getDecimalSeparator(); 3684 percent = symbols.getPercent(); 3685 perMill = symbols.getPerMill(); 3686 digit = symbols.getDigit(); 3687 separator = symbols.getPatternSeparator(); 3688 exponent = symbols.getExponentSeparator(); 3689 plus = symbols.getPlusSign(); 3690 padEscape = symbols.getPadEscape(); 3691 minus = symbols.getMinusSign(); } 3693 char nineDigit = (char) (zeroDigit + 9); 3694 3695 boolean gotNegative = false; 3696 3697 int pos = 0; 3698 for (int part=0; part<2 && pos<pattern.length(); ++part) { 3701 int subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0; 3707 3708 StringBuffer prefix = new StringBuffer (); 3715 StringBuffer suffix = new StringBuffer (); 3716 int decimalPos = -1; 3717 int multiplier = 1; 3718 int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0; 3719 byte groupingCount = -1; 3720 byte groupingCount2 = -1; 3721 int padPos = -1; 3722 char padChar = 0; 3723 int incrementPos = -1; 3724 long incrementVal = 0; 3725 byte expDigits = -1; 3726 boolean expSignAlways = false; 3727 boolean isCurrency = false; 3728 3729 StringBuffer affix = prefix; 3731 3732 int start = pos; 3733 3734 PARTLOOP: 3735 for (; pos < pattern.length(); ++pos) { 3736 char ch = pattern.charAt(pos); 3737 switch (subpart) { 3738 case 0: if (ch == digit) { 3749 if (zeroDigitCount > 0 || sigDigitCount > 0) { 3750 ++digitRightCount; 3751 } else { 3752 ++digitLeftCount; 3753 } 3754 if (groupingCount >= 0 && decimalPos < 0) { 3755 ++groupingCount; 3756 } 3757 } else if ((ch >= zeroDigit && ch <= nineDigit) || 3758 ch == sigDigit) { 3759 if (digitRightCount > 0) { 3760 patternError("Unexpected '" + ch + '\'', pattern); 3761 } 3762 if (ch == sigDigit) { 3763 ++sigDigitCount; 3764 } else { 3765 ++zeroDigitCount; 3766 if (ch != zeroDigit) { 3767 int p = digitLeftCount + zeroDigitCount 3768 + digitRightCount; 3769 if (incrementPos >= 0) { 3770 while (incrementPos < p) { 3771 incrementVal *= 10; 3772 ++incrementPos; 3773 } 3774 } else { 3775 incrementPos = p; 3776 } 3777 incrementVal += ch - zeroDigit; 3778 } 3779 } 3780 if (groupingCount >= 0 && decimalPos < 0) { 3781 ++groupingCount; 3782 } 3783 } else if (ch == groupingSeparator) { 3784 3789 if (ch == QUOTE && (pos+1) < pattern.length()) { 3790 char after = pattern.charAt(pos+1); 3791 if (!(after == digit || (after >= zeroDigit && after <= nineDigit))) { 3792 if (after == QUOTE) { 3796 ++pos; 3797 } else { 3799 if (groupingCount < 0) { 3800 subpart = 3; } else { 3802 subpart = 2; affix = suffix; 3805 sub0Limit = pos--; 3806 } 3807 continue; 3808 } 3809 } 3810 } 3811 3812 if (decimalPos >= 0) { 3813 patternError("Grouping separator after decimal", pattern); 3814 } 3815 groupingCount2 = groupingCount; 3816 groupingCount = 0; 3817 } else if (ch == decimalSeparator) { 3818 if (decimalPos >= 0) { 3819 patternError("Multiple decimal separators", pattern); 3820 } 3821 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; 3825 } else { 3826 if (pattern.regionMatches(pos, exponent, 0, exponent.length())) { 3827 if (expDigits >= 0) { 3828 patternError("Multiple exponential symbols", pattern); 3829 } 3830 if (groupingCount >= 0) { 3831 patternError("Grouping separator in exponential", pattern); 3832 } 3833 pos += exponent.length(); 3834 if (pos < pattern.length() 3836 && pattern.charAt(pos) == plus) { 3837 expSignAlways = true; 3838 ++pos; 3839 } 3840 expDigits = 0; 3843 while (pos < pattern.length() && 3844 pattern.charAt(pos) == zeroDigit) { 3845 ++expDigits; 3846 ++pos; 3847 } 3848 3849 if (((digitLeftCount + zeroDigitCount) < 1 && 3853 (sigDigitCount + digitRightCount) < 1) || 3854 (sigDigitCount > 0 && digitLeftCount > 0) || 3855 expDigits < 1) { 3856 patternError("Malformed exponential", pattern); 3857 } 3858 } 3859 subpart = 2; affix = suffix; 3862 sub0Limit = pos--; continue; 3864 } 3865 break; 3866 case 1: case 2: 3872 if (ch == digit || 3876 ch == groupingSeparator || 3877 ch == decimalSeparator || 3878 (ch >= zeroDigit && ch <= nineDigit) || 3879 ch == sigDigit) { 3880 if (subpart == 1) { subpart = 0; sub0Start = pos--; continue; 3886 } else if (ch == QUOTE) { 3887 3892 if ((pos+1) < pattern.length() && 3896 pattern.charAt(pos+1) == QUOTE) { 3897 ++pos; 3898 affix.append(ch); 3899 } else { 3900 subpart += 2; } 3902 continue; 3903 } 3904 patternError("Unquoted special character '" + ch + '\'', pattern); 3905 } else if (ch == CURRENCY_SIGN) { 3906 boolean doubled = (pos + 1) < pattern.length() && 3909 pattern.charAt(pos + 1) == CURRENCY_SIGN; 3910 3914 if (doubled) { 3915 ++pos; affix.append(ch); } 3918 isCurrency = true; 3919 } else if (ch == QUOTE) { 3921 if((pos+1) < pattern.length()&& 3925 pattern.charAt(pos+1)==QUOTE){ 3926 ++pos; 3927 affix.append(ch); }else{ 3929 subpart += 2; } 3931 } else if (ch == separator) { 3933 if (subpart == 1 || part == 1) { 3936 patternError("Unquoted special character '" + ch + '\'', pattern); 3937 } 3938 sub2Limit = pos++; 3939 break PARTLOOP; } else if (ch == percent || ch == perMill) { 3941 if (multiplier != 1) { 3943 patternError("Too many percent/permille characters", pattern); 3944 } 3945 multiplier = (ch == percent) ? 100 : 1000; 3946 ch = (ch == percent) ? PATTERN_PERCENT : PATTERN_PER_MILLE; 3948 } else if (ch == minus) { 3950 ch = PATTERN_MINUS; 3952 } else if (ch == padEscape) { 3954 if (padPos >= 0) { 3955 patternError("Multiple pad specifiers", pattern); 3956 } 3957 if ((pos+1) == pattern.length()) { 3958 patternError("Invalid pad specifier", pattern); 3959 } 3960 padPos = pos++; padChar = pattern.charAt(pos); 3962 continue; 3963 } 3964 affix.append(ch); 3965 break; 3966 case 3: case 4: if (ch == QUOTE) { 3972 if ((pos+1) < pattern.length() && 3973 pattern.charAt(pos+1) == QUOTE) { 3974 ++pos; 3975 affix.append(ch); 3976 } else { 3977 subpart -= 2; } 3979 } 3981 affix.append(ch); 3986 break; 3987 } 3988 } 3989 3990 if (subpart == 3 || subpart == 4) { 3991 patternError("Unterminated quote", pattern); 3992 } 3993 3994 if (sub0Limit == 0) { 3995 sub0Limit = pattern.length(); 3996 } 3997 3998 if (sub2Limit == 0) { 3999 sub2Limit = pattern.length(); 4000 } 4001 4002 4015 if (zeroDigitCount == 0 && sigDigitCount == 0 && 4016 digitLeftCount > 0 && decimalPos >= 0) { 4017 int n = decimalPos; 4019 if (n == 0) ++n; digitRightCount = digitLeftCount - n; 4021 digitLeftCount = n - 1; 4022 zeroDigitCount = 1; 4023 } 4024 4025 if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || 4027 (decimalPos >= 0 && 4028 (sigDigitCount > 0 || 4029 decimalPos < digitLeftCount || 4030 decimalPos > (digitLeftCount + zeroDigitCount))) || 4031 groupingCount == 0 || groupingCount2 == 0 || 4032 (sigDigitCount > 0 && zeroDigitCount > 0) || 4033 subpart > 2) { patternError("Malformed pattern", pattern); 4035 } 4036 4037 if (padPos >= 0) { 4039 if (padPos == start) { 4040 padPos = PAD_BEFORE_PREFIX; 4041 } else if (padPos+2 == sub0Start) { 4042 padPos = PAD_AFTER_PREFIX; 4043 } else if (padPos == sub0Limit) { 4044 padPos = PAD_BEFORE_SUFFIX; 4045 } else if (padPos+2 == sub2Limit) { 4046 padPos = PAD_AFTER_SUFFIX; 4047 } else { 4048 patternError("Illegal pad position", pattern); 4049 } 4050 } 4051 4052 if (part == 0) { 4053 4059 posPrefixPattern = negPrefixPattern = prefix.toString(); 4060 posSuffixPattern = negSuffixPattern = suffix.toString(); 4061 4062 useExponentialNotation = (expDigits >= 0); 4063 if (useExponentialNotation) { 4064 minExponentDigits = expDigits; 4065 exponentSignAlwaysShown = expSignAlways; 4066 } 4067 isCurrencyFormat = isCurrency; 4068 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; 4069 int effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount; 4074 boolean useSigDig = (sigDigitCount > 0); 4075 setSignificantDigitsUsed(useSigDig); 4076 if (useSigDig) { 4077 setMinimumSignificantDigits(sigDigitCount); 4078 setMaximumSignificantDigits(sigDigitCount + digitRightCount); 4079 } else { 4080 int minInt = effectiveDecimalPos - digitLeftCount; 4081 setMinimumIntegerDigits(minInt); 4082 4085 setMaximumIntegerDigits(useExponentialNotation 4086 ? digitLeftCount + minInt : DOUBLE_INTEGER_DIGITS); 4087 setMaximumFractionDigits(decimalPos >= 0 4088 ? (digitTotalCount - decimalPos) : 0); 4089 setMinimumFractionDigits(decimalPos >= 0 4090 ? (digitLeftCount + zeroDigitCount - decimalPos) : 0); 4091 } 4092 setGroupingUsed(groupingCount > 0); 4093 this.groupingSize = (groupingCount > 0) ? groupingCount : 0; 4094 this.groupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) 4095 ? groupingCount2 : 0; 4096 this.multiplier = multiplier; 4097 setDecimalSeparatorAlwaysShown(decimalPos == 0 4098 || decimalPos == digitTotalCount); 4099 if (padPos >= 0) { 4100 padPosition = padPos; 4101 formatWidth = sub0Limit - sub0Start; pad = padChar; 4103 } else { 4104 formatWidth = 0; 4105 } 4106 if (incrementVal != 0) { 4107 int scale = incrementPos - effectiveDecimalPos; 4110 roundingIncrementICU = 4111 BigDecimal.valueOf(incrementVal, scale > 0 ? scale : 0); 4112 if (scale < 0) { 4113 roundingIncrementICU = 4114 roundingIncrementICU.movePointRight(-scale); 4115 } 4116 setRoundingDouble(); 4117 roundingMode = BigDecimal.ROUND_HALF_EVEN; 4118 } else { 4119 setRoundingIncrement((BigDecimal)null); 4120 } 4121 } else { 4122 4126 negPrefixPattern = prefix.toString(); 4127 negSuffixPattern = suffix.toString(); 4128 gotNegative = true; 4129 } 4130 } 4131 4132 4136 if (pattern.length() == 0) { 4137 posPrefixPattern = posSuffixPattern = ""; 4138 setMinimumIntegerDigits(0); 4139 setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS); 4140 setMinimumFractionDigits(0); 4141 setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS); 4142 } 4143 4144 4151 if (!gotNegative || 4152 (negPrefixPattern.equals(posPrefixPattern) 4153 && negSuffixPattern.equals(posSuffixPattern))) { 4154 negSuffixPattern = posSuffixPattern; 4155 negPrefixPattern = PATTERN_MINUS + posPrefixPattern; 4156 } 4157 4162 expandAffixes(); 4163 4164 if (formatWidth > 0) { 4166 formatWidth += positivePrefix.length() + positiveSuffix.length(); 4167 } 4168 4169 setLocale(null, null); 4170 } 4171 4172 4175 private void setRoundingDouble() { 4176 if (roundingIncrementICU == null) { 4177 roundingDouble = 0.0d; 4178 roundingDoubleReciprocal = 0.0d; 4179 } else { 4180 roundingDouble = roundingIncrementICU.doubleValue(); 4181 setRoundingDoubleReciprocal(BigDecimal.ONE.divide(roundingIncrementICU,BigDecimal.ROUND_HALF_EVEN).doubleValue()); 4182 } 4183 } 4184 4185 private void patternError(String msg, String pattern) { 4186 throw new IllegalArgumentException (msg + " in pattern \"" + pattern + '"'); 4187 } 4188 4189 4193 4199 public void setMaximumIntegerDigits(int newValue) { 4200 super.setMaximumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS)); 4201 } 4202 4203 4209 public void setMinimumIntegerDigits(int newValue) { 4210 super.setMinimumIntegerDigits(Math.min(newValue, DOUBLE_INTEGER_DIGITS)); 4211 } 4212 4213 4220 public int getMinimumSignificantDigits() { 4221 return minSignificantDigits; 4222 } 4223 4224 4231 public int getMaximumSignificantDigits() { 4232 return maxSignificantDigits; 4233 } 4234 4235 4244 public void setMinimumSignificantDigits(int min) { 4245 if (min < 1) { 4246 min = 1; 4247 } 4248 int max = Math.max(maxSignificantDigits, min); 4250 minSignificantDigits = min; 4251 maxSignificantDigits = max; 4252 } 4253 4254 4263 public void setMaximumSignificantDigits(int max) { 4264 if (max < 1) { 4265 max = 1; 4266 } 4267 int min = Math.min(minSignificantDigits, max); 4269 minSignificantDigits = min; 4270 maxSignificantDigits = max; 4271 } 4272 4273 4279 public boolean areSignificantDigitsUsed() { 4280 return useSignificantDigits; 4281 } 4282 4283 4290 public void setSignificantDigitsUsed(boolean useSignificantDigits) { 4291 this.useSignificantDigits = useSignificantDigits; 4292 } 4293 4294 4304 public void setCurrency(Currency theCurrency) { 4305 4310 super.setCurrency(theCurrency); 4311 if (theCurrency != null) { 4312 boolean[] isChoiceFormat = new boolean[1]; 4313 String s = theCurrency.getName(symbols.getULocale(), 4314 Currency.SYMBOL_NAME, 4315 isChoiceFormat); 4316 symbols.setCurrencySymbol(s); 4317 symbols.setInternationalCurrencySymbol(theCurrency.getCurrencyCode()); 4318 } 4319 4320 if (isCurrencyFormat) { 4321 if (theCurrency != null) { 4322 setRoundingIncrement(theCurrency.getRoundingIncrement()); 4323 4324 int d = theCurrency.getDefaultFractionDigits(); 4325 setMinimumFractionDigits(d); 4326 setMaximumFractionDigits(d); 4327 } 4328 expandAffixes(); 4329 } 4330 } 4331 4332 4339 protected Currency getEffectiveCurrency() { 4340 Currency c = getCurrency(); 4341 if (c == null) { 4342 c = Currency.getInstance(symbols.getInternationalCurrencySymbol()); 4343 } 4344 return c; 4345 } 4346 4347 4353 public void setMaximumFractionDigits(int newValue) { 4354 super.setMaximumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS)); 4355 } 4356 4357 4363 public void setMinimumFractionDigits(int newValue) { 4364 super.setMinimumFractionDigits(Math.min(newValue, DOUBLE_FRACTION_DIGITS)); 4365 } 4366 4367 4374 public void setParseBigDecimal(boolean value) { 4375 parseBigDecimal = value; 4376 } 4377 4378 4383 public boolean isParseBigDecimal() { 4384 return parseBigDecimal; 4385 } 4386 4387 4398 4406 private void readObject(ObjectInputStream stream) 4407 throws IOException , ClassNotFoundException 4408 { 4409 stream.defaultReadObject(); 4410 4413 4421 4424 if (getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS) { 4425 setMaximumIntegerDigits(DOUBLE_INTEGER_DIGITS); 4426 } 4427 if (getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { 4428 setMaximumFractionDigits(DOUBLE_FRACTION_DIGITS); 4429 } 4430 if (serialVersionOnStream < 2) { 4431 exponentSignAlwaysShown = false; 4432 setInternalRoundingIncrement(null); 4433 setRoundingDouble(); 4434 roundingMode = BigDecimal.ROUND_HALF_EVEN; 4435 formatWidth = 0; 4436 pad = ' '; 4437 padPosition = PAD_BEFORE_PREFIX; 4438 if (serialVersionOnStream < 1) { 4439 useExponentialNotation = false; 4441 } 4442 } 4443 if (serialVersionOnStream < 3) { 4444 setCurrencyForSymbols(); 4447 } 4448 serialVersionOnStream = currentSerialVersion; 4449 digitList = new DigitList(); 4450 4451 } 4458 4459 4460 private void setInternalRoundingIncrement(BigDecimal value) { 4461 roundingIncrementICU = value; 4462 } 4466 4467 4471 private transient DigitList digitList = new DigitList(); 4472 4473 4479 private String positivePrefix = ""; 4480 4481 4488 private String positiveSuffix = ""; 4489 4490 4496 private String negativePrefix = "-"; 4497 4498 4505 private String negativeSuffix = ""; 4506 4507 4521 private String posPrefixPattern; 4523 4524 4532 private String posSuffixPattern; 4534 4535 4543 private String negPrefixPattern; 4545 4546 4554 private String negSuffixPattern; 4556 4557 4562 private ChoiceFormat currencyChoice; 4563 4564 4570 private int multiplier = 1; 4571 4572 4581 private byte groupingSize = 3; 4583 4590 private byte groupingSize2 = 0; 4591 4592 4599 private boolean decimalSeparatorAlwaysShown = false; 4600 4601 4605 private transient boolean isCurrencyFormat = false; 4606 4607 4616 private DecimalFormatSymbols symbols = null; 4618 4624 private boolean useSignificantDigits = false; 4625 4626 4633 private int minSignificantDigits = 1; 4634 4635 4642 private int maxSignificantDigits = 6; 4643 4644 4654 private boolean useExponentialNotation; 4656 4667 private byte minExponentDigits; 4669 4678 private boolean exponentSignAlwaysShown = false; 4679 4680 4696 4707 private transient BigDecimal roundingIncrementICU = null; 4708 4709 4715 private transient double roundingDouble = 0.0; 4716 4717 4722 private transient double roundingDoubleReciprocal = 0.0; 4723 4724 4734 private int roundingMode = BigDecimal.ROUND_HALF_EVEN; 4735 4736 4743 private int formatWidth = 0; 4744 4745 4752 private char pad = ' '; 4753 4754 4763 private int padPosition = PAD_BEFORE_PREFIX; 4764 4765 4774 private boolean parseBigDecimal = false; 4775 4776 4778 static final int currentSerialVersion = 3; 4779 4780 4792 private int serialVersionOnStream = currentSerialVersion; 4793 4794 4798 4810 public static final int PAD_BEFORE_PREFIX = 0; 4811 4812 4824 public static final int PAD_AFTER_PREFIX = 1; 4825 4826 4838 public static final int PAD_BEFORE_SUFFIX = 2; 4839 4840 4852 public static final int PAD_AFTER_SUFFIX = 3; 4853 4854 private static final char PATTERN_ZERO_DIGIT = '0'; 4856 private static final char PATTERN_GROUPING_SEPARATOR = ','; 4857 private static final char PATTERN_DECIMAL_SEPARATOR = '.'; 4858 private static final char PATTERN_DIGIT = '#'; 4859 static final char PATTERN_SIGNIFICANT_DIGIT = '@'; 4860 static final char PATTERN_EXPONENT = 'E'; static final char PATTERN_PLUS_SIGN = '+'; 4863 private static final char PATTERN_PER_MILLE = '\u2030'; 4865 private static final char PATTERN_PERCENT = '%'; 4866 static final char PATTERN_PAD_ESCAPE = '*'; 4871 private static final char PATTERN_MINUS = '-'; 4873 private static final char PATTERN_SEPARATOR = ';'; 4875 4876 4879 4888 private static final char CURRENCY_SIGN = '\u00A4'; 4889 4890 private static final char QUOTE = '\''; 4891 4892 4895 static final int DOUBLE_INTEGER_DIGITS = 309; 4896 static final int DOUBLE_FRACTION_DIGITS = 340; 4897 4898 4907 static final int MAX_SCIENTIFIC_INTEGER_DIGITS = 8; 4908 4909 private static final long serialVersionUID = 2; 4912 private ArrayList attributes = new ArrayList (); 4917} 4918 4919 | Popular Tags |