1 7 8 20 21 package java.text; 22 23 import java.io.InvalidObjectException ; 24 import java.io.IOException ; 25 import java.io.ObjectInputStream ; 26 import java.math.BigDecimal ; 27 import java.math.BigInteger ; 28 import java.util.ArrayList ; 29 import java.util.Currency ; 30 import java.util.Hashtable ; 31 import java.util.Locale ; 32 import java.util.ResourceBundle ; 33 import sun.text.resources.LocaleData; 34 35 357 public class DecimalFormat extends NumberFormat { 358 359 374 public DecimalFormat() { 375 Locale def = Locale.getDefault(); 376 String pattern = (String ) cachedLocaleData.get(def); 378 if (pattern == null) { 379 ResourceBundle rb = LocaleData.getLocaleElements(def); 381 String [] all = rb.getStringArray("NumberPatterns"); 382 pattern = all[0]; 383 384 cachedLocaleData.put(def, pattern); 385 } 386 387 this.symbols = new DecimalFormatSymbols (def); 389 applyPattern(pattern, false); 390 } 391 392 393 411 public DecimalFormat(String pattern) { 412 this.symbols = new DecimalFormatSymbols (Locale.getDefault()); 414 applyPattern(pattern, false); 415 } 416 417 418 439 public DecimalFormat (String pattern, DecimalFormatSymbols symbols) { 440 this.symbols = (DecimalFormatSymbols )symbols.clone(); 442 applyPattern(pattern, false); 443 } 444 445 446 465 public final StringBuffer format(Object number, 466 StringBuffer toAppendTo, 467 FieldPosition pos) { 468 if (number instanceof Long || number instanceof Integer || 469 number instanceof Short || number instanceof Byte || 470 (number instanceof BigInteger && 471 ((BigInteger )number).bitLength () < 64)) { 472 return format(((Number )number).longValue(), toAppendTo, pos); 473 } else if (number instanceof BigDecimal ) { 474 return format((BigDecimal )number, toAppendTo, pos); 475 } else if (number instanceof BigInteger ) { 476 return format((BigInteger )number, toAppendTo, pos); 477 } else if (number instanceof Number ) { 478 return format(((Number )number).doubleValue(), toAppendTo, pos); 479 } else { 480 throw new IllegalArgumentException ("Cannot format given Object as a Number"); 481 } 482 } 483 484 493 public StringBuffer format(double number, StringBuffer result, 494 FieldPosition fieldPosition) { 495 fieldPosition.setBeginIndex(0); 496 fieldPosition.setEndIndex(0); 497 498 return format(number, result, fieldPosition.getFieldDelegate()); 499 } 500 501 508 private StringBuffer format(double number, StringBuffer result, 509 FieldDelegate delegate) { 510 if (Double.isNaN(number) || 511 (Double.isInfinite(number) && multiplier == 0)) { 512 int iFieldStart = result.length(); 513 result.append(symbols.getNaN()); 514 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, 515 iFieldStart, result.length(), result); 516 return result; 517 } 518 519 529 boolean isNegative = ((number < 0.0) || (number == 0.0 && 1/number < 0.0)) ^ (multiplier < 0); 530 531 if (multiplier != 1) { 532 number *= multiplier; 533 } 534 535 if (Double.isInfinite(number)) { 536 if (isNegative) { 537 append(result, negativePrefix, delegate, 538 getNegativePrefixFieldPositions(), Field.SIGN); 539 } else { 540 append(result, positivePrefix, delegate, 541 getPositivePrefixFieldPositions(), Field.SIGN); 542 } 543 544 int iFieldStart = result.length(); 545 result.append(symbols.getInfinity()); 546 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, 547 iFieldStart, result.length(), result); 548 549 if (isNegative) { 550 append(result, negativeSuffix, delegate, 551 getNegativeSuffixFieldPositions(), Field.SIGN); 552 } else { 553 append(result, positiveSuffix, delegate, 554 getPositiveSuffixFieldPositions(), Field.SIGN); 555 } 556 557 return result; 558 } 559 560 if (isNegative) { 561 number = -number; 562 } 563 564 assert(number >= 0 && !Double.isInfinite(number)); 566 567 synchronized(digitList) { 568 int maxIntDigits = super.getMaximumIntegerDigits(); 569 int minIntDigits = super.getMinimumIntegerDigits(); 570 int maxFraDigits = super.getMaximumFractionDigits(); 571 int minFraDigits = super.getMinimumFractionDigits(); 572 573 digitList.set(number, useExponentialNotation ? 574 maxIntDigits + maxFraDigits : maxFraDigits, 575 !useExponentialNotation); 576 return subformat(result, delegate, isNegative, false, 577 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); 578 } 579 } 580 581 590 public StringBuffer format(long number, StringBuffer result, 591 FieldPosition fieldPosition) { 592 fieldPosition.setBeginIndex(0); 593 fieldPosition.setEndIndex(0); 594 595 return format(number, result, fieldPosition.getFieldDelegate()); 596 } 597 598 606 private StringBuffer format(long number, StringBuffer result, 607 FieldDelegate delegate) { 608 boolean isNegative = (number < 0); 609 if (isNegative) { 610 number = -number; 611 } 612 613 boolean useBigInteger = false; 620 if (number < 0) { if (multiplier != 0) { 622 useBigInteger = true; 623 } 624 } else if (multiplier != 1 && multiplier != 0) { 625 long cutoff = Long.MAX_VALUE / multiplier; 626 if (cutoff < 0) { 627 cutoff = -cutoff; 628 } 629 useBigInteger = (number > cutoff); 630 } 631 632 if (useBigInteger) { 633 if (isNegative) { 634 number = -number; 635 } 636 BigInteger bigIntegerValue = BigInteger.valueOf(number); 637 return format(bigIntegerValue, result, delegate, true); 638 } 639 640 number *= multiplier; 641 if (number == 0) { 642 isNegative = false; 643 } else { 644 if (multiplier < 0) { 645 number = -number; 646 isNegative = !isNegative; 647 } 648 } 649 650 synchronized(digitList) { 651 int maxIntDigits = super.getMaximumIntegerDigits(); 652 int minIntDigits = super.getMinimumIntegerDigits(); 653 int maxFraDigits = super.getMaximumFractionDigits(); 654 int minFraDigits = super.getMinimumFractionDigits(); 655 656 digitList.set(number, 657 useExponentialNotation ? maxIntDigits + maxFraDigits : 0); 658 659 return subformat(result, delegate, isNegative, true, 660 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); 661 } 662 } 663 664 673 private StringBuffer format(BigDecimal number, StringBuffer result, 674 FieldPosition fieldPosition) { 675 fieldPosition.setBeginIndex(0); 676 fieldPosition.setEndIndex(0); 677 return format(number, result, fieldPosition.getFieldDelegate()); 678 } 679 680 687 private StringBuffer format(BigDecimal number, StringBuffer result, 688 FieldDelegate delegate) { 689 if (multiplier != 1) { 690 number = number.multiply(getBigDecimalMultiplier()); 691 } 692 boolean isNegative = number.signum() == -1; 693 if (isNegative) { 694 number = number.negate(); 695 } 696 697 synchronized(digitList) { 698 int maxIntDigits = getMaximumIntegerDigits(); 699 int minIntDigits = getMinimumIntegerDigits(); 700 int maxFraDigits = getMaximumFractionDigits(); 701 int minFraDigits = getMinimumFractionDigits(); 702 int maximumDigits = maxIntDigits + maxFraDigits; 703 704 digitList.set(number, useExponentialNotation ? 705 ((maximumDigits < 0) ? Integer.MAX_VALUE : maximumDigits) : 706 maxFraDigits, !useExponentialNotation); 707 708 return subformat(result, delegate, isNegative, false, 709 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); 710 } 711 } 712 713 722 private StringBuffer format(BigInteger number, StringBuffer result, 723 FieldPosition fieldPosition) { 724 fieldPosition.setBeginIndex(0); 725 fieldPosition.setEndIndex(0); 726 727 return format(number, result, fieldPosition.getFieldDelegate(), false); 728 } 729 730 738 private StringBuffer format(BigInteger number, StringBuffer result, 739 FieldDelegate delegate, boolean formatLong) { 740 if (multiplier != 1) { 741 number = number.multiply(getBigIntegerMultiplier()); 742 } 743 boolean isNegative = number.signum() == -1; 744 if (isNegative) { 745 number = number.negate(); 746 } 747 748 synchronized(digitList) { 749 int maxIntDigits, minIntDigits, maxFraDigits, minFraDigits, maximumDigits; 750 if (formatLong) { 751 maxIntDigits = super.getMaximumIntegerDigits(); 752 minIntDigits = super.getMinimumIntegerDigits(); 753 maxFraDigits = super.getMaximumFractionDigits(); 754 minFraDigits = super.getMinimumFractionDigits(); 755 maximumDigits = maxIntDigits + maxFraDigits; 756 } else { 757 maxIntDigits = getMaximumIntegerDigits(); 758 minIntDigits = getMinimumIntegerDigits(); 759 maxFraDigits = getMaximumFractionDigits(); 760 minFraDigits = getMinimumFractionDigits(); 761 maximumDigits = maxIntDigits + maxFraDigits; 762 if (maximumDigits < 0) { 763 maximumDigits = Integer.MAX_VALUE; 764 } 765 } 766 767 digitList.set(number, useExponentialNotation ? maximumDigits : 0); 768 769 return subformat(result, delegate, isNegative, true, 770 maxIntDigits, minIntDigits, maxFraDigits, minFraDigits); 771 } 772 } 773 774 791 public AttributedCharacterIterator formatToCharacterIterator(Object obj) { 792 CharacterIteratorFieldDelegate delegate = 793 new CharacterIteratorFieldDelegate (); 794 StringBuffer sb = new StringBuffer (); 795 796 if (obj instanceof Double || obj instanceof Float ) { 797 format(((Number )obj).doubleValue(), sb, delegate); 798 } else if (obj instanceof Long || obj instanceof Integer || 799 obj instanceof Short || obj instanceof Byte ) { 800 format(((Number )obj).longValue(), sb, delegate); 801 } else if (obj instanceof BigDecimal ) { 802 format((BigDecimal )obj, sb, delegate); 803 } else if (obj instanceof BigInteger ) { 804 format((BigInteger )obj, sb, delegate, false); 805 } else if (obj == null) { 806 throw new NullPointerException ( 807 "formatToCharacterIterator must be passed non-null object"); 808 } else { 809 throw new IllegalArgumentException ( 810 "Cannot format given Object as a Number"); 811 } 812 return delegate.getIterator(sb.toString()); 813 } 814 815 819 private StringBuffer subformat(StringBuffer result, FieldDelegate delegate, 820 boolean isNegative, boolean isInteger, 821 int maxIntDigits, int minIntDigits, 822 int maxFraDigits, int minFraDigits) { 823 837 char zero = symbols.getZeroDigit(); 838 int zeroDelta = zero - '0'; char grouping = symbols.getGroupingSeparator(); 840 char decimal = isCurrencyFormat ? 841 symbols.getMonetaryDecimalSeparator() : 842 symbols.getDecimalSeparator(); 843 844 850 if (digitList.isZero()) { 851 digitList.decimalAt = 0; } 853 854 if (isNegative) { 855 append(result, negativePrefix, delegate, 856 getNegativePrefixFieldPositions(), Field.SIGN); 857 } else { 858 append(result, positivePrefix, delegate, 859 getPositivePrefixFieldPositions(), Field.SIGN); 860 } 861 862 if (useExponentialNotation) { 863 int iFieldStart = result.length(); 864 int iFieldEnd = -1; 865 int fFieldStart = -1; 866 867 871 int exponent = digitList.decimalAt; 879 int repeat = maxIntDigits; 880 int minimumIntegerDigits = minIntDigits; 881 if (repeat > 1 && repeat > minIntDigits) { 882 if (exponent >= 1) { 888 exponent = ((exponent - 1) / repeat) * repeat; 889 } else { 890 exponent = ((exponent - repeat) / repeat) * repeat; 892 } 893 minimumIntegerDigits = 1; 894 } else { 895 exponent -= minimumIntegerDigits; 897 } 898 899 int minimumDigits = minIntDigits + minFraDigits; 904 if (minimumDigits < 0) { minimumDigits = Integer.MAX_VALUE; 906 } 907 908 int integerDigits = digitList.isZero() ? minimumIntegerDigits : 911 digitList.decimalAt - exponent; 912 if (minimumDigits < integerDigits) { 913 minimumDigits = integerDigits; 914 } 915 int totalDigits = digitList.count; 916 if (minimumDigits > totalDigits) { 917 totalDigits = minimumDigits; 918 } 919 boolean addedDecimalSeparator = false; 920 921 for (int i=0; i<totalDigits; ++i) { 922 if (i == integerDigits) { 923 iFieldEnd = result.length(); 925 926 result.append(decimal); 927 addedDecimalSeparator = true; 928 929 fFieldStart = result.length(); 931 } 932 result.append((i < digitList.count) ? 933 (char)(digitList.digits[i] + zeroDelta) : 934 zero); 935 } 936 937 if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) { 938 iFieldEnd = result.length(); 940 941 result.append(decimal); 942 addedDecimalSeparator = true; 943 944 fFieldStart = result.length(); 946 } 947 948 if (iFieldEnd == -1) { 950 iFieldEnd = result.length(); 951 } 952 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, 953 iFieldStart, iFieldEnd, result); 954 if (addedDecimalSeparator) { 955 delegate.formatted(Field.DECIMAL_SEPARATOR, 956 Field.DECIMAL_SEPARATOR, 957 iFieldEnd, fFieldStart, result); 958 } 959 if (fFieldStart == -1) { 960 fFieldStart = result.length(); 961 } 962 delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION, 963 fFieldStart, result.length(), result); 964 965 int fieldStart = result.length(); 970 971 result.append(symbols.getExponentialSymbol()); 972 973 delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL, 974 fieldStart, result.length(), result); 975 976 if (digitList.isZero()) { 980 exponent = 0; 981 } 982 983 boolean negativeExponent = exponent < 0; 984 if (negativeExponent) { 985 exponent = -exponent; 986 fieldStart = result.length(); 987 result.append(symbols.getMinusSign()); 988 delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN, 989 fieldStart, result.length(), result); 990 } 991 digitList.set(exponent); 992 993 int eFieldStart = result.length(); 994 995 for (int i=digitList.decimalAt; i<minExponentDigits; ++i) { 996 result.append(zero); 997 } 998 for (int i=0; i<digitList.decimalAt; ++i) { 999 result.append((i < digitList.count) ? 1000 (char)(digitList.digits[i] + zeroDelta) : zero); 1001 } 1002 delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart, 1003 result.length(), result); 1004 } else { 1005 int iFieldStart = result.length(); 1006 1007 int count = minIntDigits; 1012 int digitIndex = 0; if (digitList.decimalAt > 0 && count < digitList.decimalAt) { 1014 count = digitList.decimalAt; 1015 } 1016 1017 if (count > maxIntDigits) { 1022 count = maxIntDigits; 1023 digitIndex = digitList.decimalAt - count; 1024 } 1025 1026 int sizeBeforeIntegerPart = result.length(); 1027 for (int i=count-1; i>=0; --i) { 1028 if (i < digitList.decimalAt && digitIndex < digitList.count) { 1029 result.append((char)(digitList.digits[digitIndex++] + zeroDelta)); 1031 } else { 1032 result.append(zero); 1034 } 1035 1036 if (isGroupingUsed() && i>0 && (groupingSize != 0) && 1040 (i % groupingSize == 0)) { 1041 int gStart = result.length(); 1042 result.append(grouping); 1043 delegate.formatted(Field.GROUPING_SEPARATOR, 1044 Field.GROUPING_SEPARATOR, gStart, 1045 result.length(), result); 1046 } 1047 } 1048 1049 boolean fractionPresent = (minFraDigits > 0) || 1052 (!isInteger && digitIndex < digitList.count); 1053 1054 if (!fractionPresent && result.length() == sizeBeforeIntegerPart) { 1058 result.append(zero); 1059 } 1060 1061 delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER, 1062 iFieldStart, result.length(), result); 1063 1064 int sStart = result.length(); 1066 if (decimalSeparatorAlwaysShown || fractionPresent) { 1067 result.append(decimal); 1068 } 1069 1070 if (sStart != result.length()) { 1071 delegate.formatted(Field.DECIMAL_SEPARATOR, 1072 Field.DECIMAL_SEPARATOR, 1073 sStart, result.length(), result); 1074 } 1075 int fFieldStart = result.length(); 1076 1077 for (int i=0; i < maxFraDigits; ++i) { 1078 if (i >= minFraDigits && 1085 (isInteger || digitIndex >= digitList.count)) { 1086 break; 1087 } 1088 1089 if (-1-i > (digitList.decimalAt-1)) { 1093 result.append(zero); 1094 continue; 1095 } 1096 1097 if (!isInteger && digitIndex < digitList.count) { 1100 result.append((char)(digitList.digits[digitIndex++] + zeroDelta)); 1101 } else { 1102 result.append(zero); 1103 } 1104 } 1105 1106 delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION, 1108 fFieldStart, result.length(), result); 1109 } 1110 1111 if (isNegative) { 1112 append(result, negativeSuffix, delegate, 1113 getNegativeSuffixFieldPositions(), Field.SIGN); 1114 } 1115 else { 1116 append(result, positiveSuffix, delegate, 1117 getPositiveSuffixFieldPositions(), Field.SIGN); 1118 } 1119 1120 return result; 1121 } 1122 1123 1136 private void append(StringBuffer result, String string, 1137 FieldDelegate delegate, 1138 FieldPosition [] positions, 1139 Format.Field signAttribute) { 1140 int start = result.length(); 1141 1142 if (string.length() > 0) { 1143 result.append(string); 1144 for (int counter = 0, max = positions.length; counter < max; 1145 counter++) { 1146 FieldPosition fp = positions[counter]; 1147 Format.Field attribute = fp.getFieldAttribute(); 1148 1149 if (attribute == Field.SIGN) { 1150 attribute = signAttribute; 1151 } 1152 delegate.formatted(attribute, attribute, 1153 start + fp.getBeginIndex(), 1154 start + fp.getEndIndex(), result); 1155 } 1156 } 1157 } 1158 1159 1215 public Number parse(String text, ParsePosition pos) { 1216 if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) { 1218 pos.index = pos.index + symbols.getNaN().length(); 1219 return new Double (Double.NaN); 1220 } 1221 1222 boolean[] status = new boolean[STATUS_LENGTH]; 1223 if (!subparse(text, pos, positivePrefix, negativePrefix, digitList, false, status)) { 1224 return null; 1225 } 1226 1227 if (status[STATUS_INFINITE]) { 1229 if (status[STATUS_POSITIVE] == (multiplier >= 0)) { 1230 return new Double (Double.POSITIVE_INFINITY); 1231 } else { 1232 return new Double (Double.NEGATIVE_INFINITY); 1233 } 1234 } 1235 1236 if (multiplier == 0) { 1237 if (digitList.isZero()) { 1238 return new Double (Double.NaN); 1239 } else if (status[STATUS_POSITIVE]) { 1240 return new Double (Double.POSITIVE_INFINITY); 1241 } else { 1242 return new Double (Double.NEGATIVE_INFINITY); 1243 } 1244 } 1245 1246 if (isParseBigDecimal()) { 1247 BigDecimal bigDecimalResult = digitList.getBigDecimal(); 1248 1249 if (multiplier != 1) { 1250 try { 1251 bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier()); 1252 } 1253 catch (ArithmeticException e) { bigDecimalResult = bigDecimalResult.divide(getBigDecimalMultiplier(), BigDecimal.ROUND_HALF_EVEN); 1255 } 1256 } 1257 1258 if (!status[STATUS_POSITIVE]) { 1259 bigDecimalResult = bigDecimalResult.negate(); 1260 } 1261 return bigDecimalResult; 1262 } else { 1263 boolean gotDouble = true; 1264 boolean gotLongMinimum = false; 1265 double doubleResult = 0.0; 1266 long longResult = 0; 1267 1268 if (digitList.fitsIntoLong(status[STATUS_POSITIVE], isParseIntegerOnly())) { 1270 gotDouble = false; 1271 longResult = digitList.getLong(); 1272 if (longResult < 0) { gotLongMinimum = true; 1274 } 1275 } else { 1276 doubleResult = digitList.getDouble(); 1277 } 1278 1279 if (multiplier != 1) { 1282 if (gotDouble) { 1283 doubleResult /= multiplier; 1284 } else { 1285 if (longResult % multiplier == 0) { 1287 longResult /= multiplier; 1288 } else { 1289 doubleResult = ((double)longResult) / multiplier; 1290 gotDouble = true; 1291 } 1292 } 1293 } 1294 1295 if (!status[STATUS_POSITIVE] && !gotLongMinimum) { 1296 doubleResult = -doubleResult; 1297 longResult = -longResult; 1298 } 1299 1300 if (multiplier != 1 && gotDouble) { 1310 longResult = (long)doubleResult; 1311 gotDouble = ((doubleResult != (double)longResult) || 1312 (doubleResult == 0.0 && 1/doubleResult < 0.0)) && 1313 !isParseIntegerOnly(); 1314 } 1315 1316 return gotDouble ? 1317 (Number )new Double (doubleResult) : (Number )new Long (longResult); 1318 } 1319 } 1320 1321 1324 private BigInteger getBigIntegerMultiplier() { 1325 if (bigIntegerMultiplier == null) { 1326 bigIntegerMultiplier = BigInteger.valueOf(multiplier); 1327 } 1328 return bigIntegerMultiplier; 1329 } 1330 private transient BigInteger bigIntegerMultiplier; 1331 1332 1335 private BigDecimal getBigDecimalMultiplier() { 1336 if (bigDecimalMultiplier == null) { 1337 bigDecimalMultiplier = new BigDecimal (multiplier); 1338 } 1339 return bigDecimalMultiplier; 1340 } 1341 private transient BigDecimal bigDecimalMultiplier; 1342 1343 private static final int STATUS_INFINITE = 0; 1344 private static final int STATUS_POSITIVE = 1; 1345 private static final int STATUS_LENGTH = 2; 1346 1347 1359 private final boolean subparse(String text, ParsePosition parsePosition, 1360 String positivePrefix, String negativePrefix, 1361 DigitList digits, boolean isExponent, 1362 boolean status[]) { 1363 int position = parsePosition.index; 1364 int oldStart = parsePosition.index; 1365 int backup; 1366 boolean gotPositive, gotNegative; 1367 1368 gotPositive = text.regionMatches(position, positivePrefix, 0, 1370 positivePrefix.length()); 1371 gotNegative = text.regionMatches(position, negativePrefix, 0, 1372 negativePrefix.length()); 1373 1374 if (gotPositive && gotNegative) { 1375 if (positivePrefix.length() > negativePrefix.length()) { 1376 gotNegative = false; 1377 } else if (positivePrefix.length() < negativePrefix.length()) { 1378 gotPositive = false; 1379 } 1380 } 1381 1382 if (gotPositive) { 1383 position += positivePrefix.length(); 1384 } else if (gotNegative) { 1385 position += negativePrefix.length(); 1386 } else { 1387 parsePosition.errorIndex = position; 1388 return false; 1389 } 1390 1391 status[STATUS_INFINITE] = false; 1393 if (!isExponent && text.regionMatches(position,symbols.getInfinity(),0, 1394 symbols.getInfinity().length())) { 1395 position += symbols.getInfinity().length(); 1396 status[STATUS_INFINITE] = true; 1397 } else { 1398 1405 digits.decimalAt = digits.count = 0; 1406 char zero = symbols.getZeroDigit(); 1407 char decimal = isCurrencyFormat ? 1408 symbols.getMonetaryDecimalSeparator() : 1409 symbols.getDecimalSeparator(); 1410 char grouping = symbols.getGroupingSeparator(); 1411 char exponentChar = symbols.getExponentialSymbol(); 1412 boolean sawDecimal = false; 1413 boolean sawExponent = false; 1414 boolean sawDigit = false; 1415 int exponent = 0; 1417 int digitCount = 0; 1420 1421 backup = -1; 1422 for (; position < text.length(); ++position) { 1423 char ch = text.charAt(position); 1424 1425 1436 int digit = ch - zero; 1437 if (digit < 0 || digit > 9) { 1438 digit = Character.digit(ch, 10); 1439 } 1440 1441 if (digit == 0) { 1442 backup = -1; sawDigit = true; 1445 1446 if (digits.count == 0) { 1448 if (!sawDecimal) { 1450 continue; 1451 } 1452 1453 --digits.decimalAt; 1458 } else { 1459 ++digitCount; 1460 digits.append((char)(digit + '0')); 1461 } 1462 } else if (digit > 0 && digit <= 9) { sawDigit = true; 1464 ++digitCount; 1465 digits.append((char)(digit + '0')); 1466 1467 backup = -1; 1469 } else if (!isExponent && ch == decimal) { 1470 if (isParseIntegerOnly() || sawDecimal) { 1473 break; 1474 } 1475 digits.decimalAt = digitCount; sawDecimal = true; 1477 } else if (!isExponent && ch == grouping && isGroupingUsed()) { 1478 if (sawDecimal) { 1479 break; 1480 } 1481 backup = position; 1485 } else if (!isExponent && ch == exponentChar && !sawExponent) { 1486 ParsePosition pos = new ParsePosition (position + 1); 1488 boolean[] stat = new boolean[STATUS_LENGTH]; 1489 DigitList exponentDigits = new DigitList (); 1490 1491 if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) && 1492 exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) { 1493 position = pos.index; exponent = (int)exponentDigits.getLong(); 1495 if (!stat[STATUS_POSITIVE]) { 1496 exponent = -exponent; 1497 } 1498 sawExponent = true; 1499 } 1500 break; } 1502 else { 1503 break; 1504 } 1505 } 1506 1507 if (backup != -1) { 1508 position = backup; 1509 } 1510 1511 if (!sawDecimal) { 1513 digits.decimalAt = digitCount; } 1515 1516 digits.decimalAt += exponent; 1518 1519 if (!sawDigit && digitCount == 0) { 1524 parsePosition.index = oldStart; 1525 parsePosition.errorIndex = oldStart; 1526 return false; 1527 } 1528 } 1529 1530 if (!isExponent) { 1532 if (gotPositive) { 1533 gotPositive = text.regionMatches(position,positiveSuffix,0, 1534 positiveSuffix.length()); 1535 } 1536 if (gotNegative) { 1537 gotNegative = text.regionMatches(position,negativeSuffix,0, 1538 negativeSuffix.length()); 1539 } 1540 1541 if (gotPositive && gotNegative) { 1543 if (positiveSuffix.length() > negativeSuffix.length()) { 1544 gotNegative = false; 1545 } else if (positiveSuffix.length() < negativeSuffix.length()) { 1546 gotPositive = false; 1547 } 1548 } 1549 1550 if (gotPositive == gotNegative) { 1552 parsePosition.errorIndex = position; 1553 return false; 1554 } 1555 1556 parsePosition.index = position + 1557 (gotPositive ? positiveSuffix.length() : negativeSuffix.length()); } else { 1559 parsePosition.index = position; 1560 } 1561 1562 status[STATUS_POSITIVE] = gotPositive; 1563 if (parsePosition.index == oldStart) { 1564 parsePosition.errorIndex = position; 1565 return false; 1566 } 1567 return true; 1568 } 1569 1570 1576 public DecimalFormatSymbols getDecimalFormatSymbols() { 1577 try { 1578 return (DecimalFormatSymbols ) symbols.clone(); 1580 } catch (Exception foo) { 1581 return null; } 1583 } 1584 1585 1586 1592 public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { 1593 try { 1594 symbols = (DecimalFormatSymbols ) newSymbols.clone(); 1596 expandAffixes(); 1597 } catch (Exception foo) { 1598 } 1600 } 1601 1602 1606 public String getPositivePrefix () { 1607 return positivePrefix; 1608 } 1609 1610 1614 public void setPositivePrefix (String newValue) { 1615 positivePrefix = newValue; 1616 posPrefixPattern = null; 1617 positivePrefixFieldPositions = null; 1618 } 1619 1620 1628 private FieldPosition [] getPositivePrefixFieldPositions() { 1629 if (positivePrefixFieldPositions == null) { 1630 if (posPrefixPattern != null) { 1631 positivePrefixFieldPositions = expandAffix(posPrefixPattern); 1632 } 1633 else { 1634 positivePrefixFieldPositions = EmptyFieldPositionArray; 1635 } 1636 } 1637 return positivePrefixFieldPositions; 1638 } 1639 1640 1644 public String getNegativePrefix () { 1645 return negativePrefix; 1646 } 1647 1648 1652 public void setNegativePrefix (String newValue) { 1653 negativePrefix = newValue; 1654 negPrefixPattern = null; 1655 } 1656 1657 1665 private FieldPosition [] getNegativePrefixFieldPositions() { 1666 if (negativePrefixFieldPositions == null) { 1667 if (negPrefixPattern != null) { 1668 negativePrefixFieldPositions = expandAffix(negPrefixPattern); 1669 } 1670 else { 1671 negativePrefixFieldPositions = EmptyFieldPositionArray; 1672 } 1673 } 1674 return negativePrefixFieldPositions; 1675 } 1676 1677 1681 public String getPositiveSuffix () { 1682 return positiveSuffix; 1683 } 1684 1685 1689 public void setPositiveSuffix (String newValue) { 1690 positiveSuffix = newValue; 1691 posSuffixPattern = null; 1692 } 1693 1694 1702 private FieldPosition [] getPositiveSuffixFieldPositions() { 1703 if (positiveSuffixFieldPositions == null) { 1704 if (posSuffixPattern != null) { 1705 positiveSuffixFieldPositions = expandAffix(posSuffixPattern); 1706 } 1707 else { 1708 positiveSuffixFieldPositions = EmptyFieldPositionArray; 1709 } 1710 } 1711 return positiveSuffixFieldPositions; 1712 } 1713 1714 1718 public String getNegativeSuffix () { 1719 return negativeSuffix; 1720 } 1721 1722 1726 public void setNegativeSuffix (String newValue) { 1727 negativeSuffix = newValue; 1728 negSuffixPattern = null; 1729 } 1730 1731 1739 private FieldPosition [] getNegativeSuffixFieldPositions() { 1740 if (negativeSuffixFieldPositions == null) { 1741 if (negSuffixPattern != null) { 1742 negativeSuffixFieldPositions = expandAffix(negSuffixPattern); 1743 } 1744 else { 1745 negativeSuffixFieldPositions = EmptyFieldPositionArray; 1746 } 1747 } 1748 return negativeSuffixFieldPositions; 1749 } 1750 1751 1757 public int getMultiplier () { 1758 return multiplier; 1759 } 1760 1761 1774 public void setMultiplier (int newValue) { 1775 multiplier = newValue; 1776 bigDecimalMultiplier = null; 1777 bigIntegerMultiplier = null; 1778 } 1779 1780 1788 public int getGroupingSize () { 1789 return groupingSize; 1790 } 1791 1792 1802 public void setGroupingSize (int newValue) { 1803 groupingSize = (byte)newValue; 1804 } 1805 1806 1811 public boolean isDecimalSeparatorAlwaysShown() { 1812 return decimalSeparatorAlwaysShown; 1813 } 1814 1815 1820 public void setDecimalSeparatorAlwaysShown(boolean newValue) { 1821 decimalSeparatorAlwaysShown = newValue; 1822 } 1823 1824 1830 public boolean isParseBigDecimal() { 1831 return parseBigDecimal; 1832 } 1833 1834 1840 public void setParseBigDecimal(boolean newValue) { 1841 parseBigDecimal = newValue; 1842 } 1843 1844 1847 public Object clone() { 1848 try { 1849 DecimalFormat other = (DecimalFormat ) super.clone(); 1850 other.symbols = (DecimalFormatSymbols ) symbols.clone(); 1851 other.digitList = (DigitList ) digitList.clone(); 1852 return other; 1853 } catch (Exception e) { 1854 throw new InternalError (); 1855 } 1856 } 1857 1858 1861 public boolean equals(Object obj) 1862 { 1863 if (obj == null) return false; 1864 if (!super.equals(obj)) return false; DecimalFormat other = (DecimalFormat ) obj; 1866 return ((posPrefixPattern == other.posPrefixPattern && 1867 positivePrefix.equals(other.positivePrefix)) 1868 || (posPrefixPattern != null && 1869 posPrefixPattern.equals(other.posPrefixPattern))) 1870 && ((posSuffixPattern == other.posSuffixPattern && 1871 positiveSuffix.equals(other.positiveSuffix)) 1872 || (posSuffixPattern != null && 1873 posSuffixPattern.equals(other.posSuffixPattern))) 1874 && ((negPrefixPattern == other.negPrefixPattern && 1875 negativePrefix.equals(other.negativePrefix)) 1876 || (negPrefixPattern != null && 1877 negPrefixPattern.equals(other.negPrefixPattern))) 1878 && ((negSuffixPattern == other.negSuffixPattern && 1879 negativeSuffix.equals(other.negativeSuffix)) 1880 || (negSuffixPattern != null && 1881 negSuffixPattern.equals(other.negSuffixPattern))) 1882 && multiplier == other.multiplier 1883 && groupingSize == other.groupingSize 1884 && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown 1885 && parseBigDecimal == other.parseBigDecimal 1886 && useExponentialNotation == other.useExponentialNotation 1887 && (!useExponentialNotation || 1888 minExponentDigits == other.minExponentDigits) 1889 && maximumIntegerDigits == other.maximumIntegerDigits 1890 && minimumIntegerDigits == other.minimumIntegerDigits 1891 && maximumFractionDigits == other.maximumFractionDigits 1892 && minimumFractionDigits == other.minimumFractionDigits 1893 && symbols.equals(other.symbols); 1894 } 1895 1896 1899 public int hashCode() { 1900 return super.hashCode() * 37 + positivePrefix.hashCode(); 1901 } 1903 1904 1909 public String toPattern() { 1910 return toPattern( false ); 1911 } 1912 1913 1918 public String toLocalizedPattern() { 1919 return toPattern( true ); 1920 } 1921 1922 1928 private void expandAffixes() { 1929 StringBuffer buffer = new StringBuffer (); 1931 if (posPrefixPattern != null) { 1932 positivePrefix = expandAffix(posPrefixPattern, buffer); 1933 positivePrefixFieldPositions = null; 1934 } 1935 if (posSuffixPattern != null) { 1936 positiveSuffix = expandAffix(posSuffixPattern, buffer); 1937 positiveSuffixFieldPositions = null; 1938 } 1939 if (negPrefixPattern != null) { 1940 negativePrefix = expandAffix(negPrefixPattern, buffer); 1941 negativePrefixFieldPositions = null; 1942 } 1943 if (negSuffixPattern != null) { 1944 negativeSuffix = expandAffix(negSuffixPattern, buffer); 1945 negativeSuffixFieldPositions = null; 1946 } 1947 } 1948 1949 1963 private String expandAffix(String pattern, StringBuffer buffer) { 1964 buffer.setLength(0); 1965 for (int i=0; i<pattern.length(); ) { 1966 char c = pattern.charAt(i++); 1967 if (c == QUOTE) { 1968 c = pattern.charAt(i++); 1969 switch (c) { 1970 case CURRENCY_SIGN: 1971 if (i<pattern.length() && 1972 pattern.charAt(i) == CURRENCY_SIGN) { 1973 ++i; 1974 buffer.append(symbols.getInternationalCurrencySymbol()); 1975 } else { 1976 buffer.append(symbols.getCurrencySymbol()); 1977 } 1978 continue; 1979 case PATTERN_PERCENT: 1980 c = symbols.getPercent(); 1981 break; 1982 case PATTERN_PER_MILLE: 1983 c = symbols.getPerMill(); 1984 break; 1985 case PATTERN_MINUS: 1986 c = symbols.getMinusSign(); 1987 break; 1988 } 1989 } 1990 buffer.append(c); 1991 } 1992 return buffer.toString(); 1993 } 1994 1995 2010 private FieldPosition [] expandAffix(String pattern) { 2011 ArrayList positions = null; 2012 int stringIndex = 0; 2013 for (int i=0; i<pattern.length(); ) { 2014 char c = pattern.charAt(i++); 2015 if (c == QUOTE) { 2016 int field = -1; 2017 Format.Field fieldID = null; 2018 c = pattern.charAt(i++); 2019 switch (c) { 2020 case CURRENCY_SIGN: 2021 String string; 2022 if (i<pattern.length() && 2023 pattern.charAt(i) == CURRENCY_SIGN) { 2024 ++i; 2025 string = symbols.getInternationalCurrencySymbol(); 2026 } else { 2027 string = symbols.getCurrencySymbol(); 2028 } 2029 if (string.length() > 0) { 2030 if (positions == null) { 2031 positions = new ArrayList (2); 2032 } 2033 FieldPosition fp = new FieldPosition (Field.CURRENCY); 2034 fp.setBeginIndex(stringIndex); 2035 fp.setEndIndex(stringIndex + string.length()); 2036 positions.add(fp); 2037 stringIndex += string.length(); 2038 } 2039 continue; 2040 case PATTERN_PERCENT: 2041 c = symbols.getPercent(); 2042 field = -1; 2043 fieldID = Field.PERCENT; 2044 break; 2045 case PATTERN_PER_MILLE: 2046 c = symbols.getPerMill(); 2047 field = -1; 2048 fieldID = Field.PERMILLE; 2049 break; 2050 case PATTERN_MINUS: 2051 c = symbols.getMinusSign(); 2052 field = -1; 2053 fieldID = Field.SIGN; 2054 break; 2055 } 2056 if (fieldID != null) { 2057 if (positions == null) { 2058 positions = new ArrayList (2); 2059 } 2060 FieldPosition fp = new FieldPosition (fieldID, field); 2061 fp.setBeginIndex(stringIndex); 2062 fp.setEndIndex(stringIndex + 1); 2063 positions.add(fp); 2064 } 2065 } 2066 stringIndex++; 2067 } 2068 if (positions != null) { 2069 return (FieldPosition [])positions.toArray(EmptyFieldPositionArray); 2070 } 2071 return EmptyFieldPositionArray; 2072 } 2073 2074 2089 private void appendAffix(StringBuffer buffer, String affixPattern, 2090 String expAffix, boolean localized) { 2091 if (affixPattern == null) { 2092 appendAffix(buffer, expAffix, localized); 2093 } else { 2094 int i; 2095 for (int pos=0; pos<affixPattern.length(); pos=i) { 2096 i = affixPattern.indexOf(QUOTE, pos); 2097 if (i < 0) { 2098 appendAffix(buffer, affixPattern.substring(pos), localized); 2099 break; 2100 } 2101 if (i > pos) { 2102 appendAffix(buffer, affixPattern.substring(pos, i), localized); 2103 } 2104 char c = affixPattern.charAt(++i); 2105 ++i; 2106 if (c == QUOTE) { 2107 buffer.append(c); 2108 } else if (c == CURRENCY_SIGN && 2110 i<affixPattern.length() && 2111 affixPattern.charAt(i) == CURRENCY_SIGN) { 2112 ++i; 2113 buffer.append(c); 2114 } else if (localized) { 2116 switch (c) { 2117 case PATTERN_PERCENT: 2118 c = symbols.getPercent(); 2119 break; 2120 case PATTERN_PER_MILLE: 2121 c = symbols.getPerMill(); 2122 break; 2123 case PATTERN_MINUS: 2124 c = symbols.getMinusSign(); 2125 break; 2126 } 2127 } 2128 buffer.append(c); 2129 } 2130 } 2131 } 2132 2133 2138 private void appendAffix(StringBuffer buffer, String affix, boolean localized) { 2139 boolean needQuote; 2140 if (localized) { 2141 needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0 2142 || affix.indexOf(symbols.getGroupingSeparator()) >= 0 2143 || affix.indexOf(symbols.getDecimalSeparator()) >= 0 2144 || affix.indexOf(symbols.getPercent()) >= 0 2145 || affix.indexOf(symbols.getPerMill()) >= 0 2146 || affix.indexOf(symbols.getDigit()) >= 0 2147 || affix.indexOf(symbols.getPatternSeparator()) >= 0 2148 || affix.indexOf(symbols.getMinusSign()) >= 0 2149 || affix.indexOf(CURRENCY_SIGN) >= 0; 2150 } 2151 else { 2152 needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0 2153 || affix.indexOf(PATTERN_GROUPING_SEPARATOR) >= 0 2154 || affix.indexOf(PATTERN_DECIMAL_SEPARATOR) >= 0 2155 || affix.indexOf(PATTERN_PERCENT) >= 0 2156 || affix.indexOf(PATTERN_PER_MILLE) >= 0 2157 || affix.indexOf(PATTERN_DIGIT) >= 0 2158 || affix.indexOf(PATTERN_SEPARATOR) >= 0 2159 || affix.indexOf(PATTERN_MINUS) >= 0 2160 || affix.indexOf(CURRENCY_SIGN) >= 0; 2161 } 2162 if (needQuote) buffer.append('\''); 2163 if (affix.indexOf('\'') < 0) buffer.append(affix); 2164 else { 2165 for (int j=0; j<affix.length(); ++j) { 2166 char c = affix.charAt(j); 2167 buffer.append(c); 2168 if (c == '\'') buffer.append(c); 2169 } 2170 } 2171 if (needQuote) buffer.append('\''); 2172 } 2173 2174 2176 private String toPattern(boolean localized) { 2177 StringBuffer result = new StringBuffer (); 2178 for (int j = 1; j >= 0; --j) { 2179 if (j == 1) 2180 appendAffix(result, posPrefixPattern, positivePrefix, localized); 2181 else appendAffix(result, negPrefixPattern, negativePrefix, localized); 2182 int i; 2183 int digitCount = useExponentialNotation 2184 ? getMaximumIntegerDigits() 2185 : Math.max(groupingSize, getMinimumIntegerDigits())+1; 2186 for (i = digitCount; i > 0; --i) { 2187 if (i != digitCount && isGroupingUsed() && groupingSize != 0 && 2188 i % groupingSize == 0) { 2189 result.append(localized ? symbols.getGroupingSeparator() : 2190 PATTERN_GROUPING_SEPARATOR); 2191 } 2192 result.append(i <= getMinimumIntegerDigits() 2193 ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT) 2194 : (localized ? symbols.getDigit() : PATTERN_DIGIT)); 2195 } 2196 if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) 2197 result.append(localized ? symbols.getDecimalSeparator() : 2198 PATTERN_DECIMAL_SEPARATOR); 2199 for (i = 0; i < getMaximumFractionDigits(); ++i) { 2200 if (i < getMinimumFractionDigits()) { 2201 result.append(localized ? symbols.getZeroDigit() : 2202 PATTERN_ZERO_DIGIT); 2203 } else { 2204 result.append(localized ? symbols.getDigit() : 2205 PATTERN_DIGIT); 2206 } 2207 } 2208 if (useExponentialNotation) 2209 { 2210 result.append(localized ? symbols.getExponentialSymbol() : 2211 PATTERN_EXPONENT); 2212 for (i=0; i<minExponentDigits; ++i) 2213 result.append(localized ? symbols.getZeroDigit() : 2214 PATTERN_ZERO_DIGIT); 2215 } 2216 if (j == 1) { 2217 appendAffix(result, posSuffixPattern, positiveSuffix, localized); 2218 if ((negSuffixPattern == posSuffixPattern && negativeSuffix.equals(positiveSuffix)) 2220 || (negSuffixPattern != null && 2221 negSuffixPattern.equals(posSuffixPattern))) { 2222 if ((negPrefixPattern != null && posPrefixPattern != null && 2223 negPrefixPattern.equals("'-" + posPrefixPattern)) || 2224 (negPrefixPattern == posPrefixPattern && negativePrefix.equals(symbols.getMinusSign() + positivePrefix))) 2226 break; 2227 } 2228 result.append(localized ? symbols.getPatternSeparator() : 2229 PATTERN_SEPARATOR); 2230 } else appendAffix(result, negSuffixPattern, negativeSuffix, localized); 2231 } 2232 return result.toString(); 2233 } 2234 2235 2256 public void applyPattern(String pattern) { 2257 applyPattern(pattern, false); 2258 } 2259 2260 2282 public void applyLocalizedPattern(String pattern) { 2283 applyPattern(pattern, true); 2284 } 2285 2286 2289 private void applyPattern(String pattern, boolean localized) { 2290 char zeroDigit = PATTERN_ZERO_DIGIT; 2291 char groupingSeparator = PATTERN_GROUPING_SEPARATOR; 2292 char decimalSeparator = PATTERN_DECIMAL_SEPARATOR; 2293 char percent = PATTERN_PERCENT; 2294 char perMill = PATTERN_PER_MILLE; 2295 char digit = PATTERN_DIGIT; 2296 char separator = PATTERN_SEPARATOR; 2297 char exponent = PATTERN_EXPONENT; 2298 char minus = PATTERN_MINUS; 2299 if (localized) { 2300 zeroDigit = symbols.getZeroDigit(); 2301 groupingSeparator = symbols.getGroupingSeparator(); 2302 decimalSeparator = symbols.getDecimalSeparator(); 2303 percent = symbols.getPercent(); 2304 perMill = symbols.getPerMill(); 2305 digit = symbols.getDigit(); 2306 separator = symbols.getPatternSeparator(); 2307 exponent = symbols.getExponentialSymbol(); 2308 minus = symbols.getMinusSign(); 2309 } 2310 boolean gotNegative = false; 2311 decimalSeparatorAlwaysShown = false; 2312 isCurrencyFormat = false; 2313 useExponentialNotation = false; 2314 2315 int phaseOneStart = 0; 2320 int phaseOneLength = 0; 2321 2322 int start = 0; 2323 for (int j = 1; j >= 0 && start < pattern.length(); --j) { 2324 boolean inQuote = false; 2325 StringBuffer prefix = new StringBuffer (); 2326 StringBuffer suffix = new StringBuffer (); 2327 int decimalPos = -1; 2328 int multiplier = 1; 2329 int digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0; 2330 byte groupingCount = -1; 2331 2332 int phase = 0; 2340 2341 StringBuffer affix = prefix; 2343 2344 for (int pos = start; pos < pattern.length(); ++pos) { 2345 char ch = pattern.charAt(pos); 2346 switch (phase) { 2347 case 0: 2348 case 2: 2349 if (inQuote) { 2351 if (ch == QUOTE) { 2355 if ((pos+1) < pattern.length() && 2356 pattern.charAt(pos+1) == QUOTE) { 2357 ++pos; 2358 affix.append("''"); } else { 2360 inQuote = false; } 2362 continue; 2363 } 2364 } else { 2365 if (ch == digit || 2368 ch == zeroDigit || 2369 ch == groupingSeparator || 2370 ch == decimalSeparator) { 2371 phase = 1; 2372 if (j == 1) { 2373 phaseOneStart = pos; 2374 } 2375 --pos; continue; 2377 } else if (ch == CURRENCY_SIGN) { 2378 boolean doubled = (pos + 1) < pattern.length() && 2381 pattern.charAt(pos + 1) == CURRENCY_SIGN; 2382 if (doubled) { ++pos; 2384 } 2385 isCurrencyFormat = true; 2386 affix.append(doubled ? "'\u00A4\u00A4" : "'\u00A4"); 2387 continue; 2388 } else if (ch == QUOTE) { 2389 if (ch == QUOTE) { 2394 if ((pos+1) < pattern.length() && 2395 pattern.charAt(pos+1) == QUOTE) { 2396 ++pos; 2397 affix.append("''"); } else { 2399 inQuote = true; } 2401 continue; 2402 } 2403 } else if (ch == separator) { 2404 if (phase == 0 || j == 0) { 2408 throw new IllegalArgumentException ("Unquoted special character '" + 2409 ch + "' in pattern \"" + pattern + '"'); 2410 } 2411 start = pos + 1; 2412 pos = pattern.length(); 2413 continue; 2414 } 2415 2416 else if (ch == percent) { 2418 if (multiplier != 1) { 2419 throw new IllegalArgumentException ("Too many percent/per mille characters in pattern \"" + 2420 pattern + '"'); 2421 } 2422 multiplier = 100; 2423 affix.append("'%"); 2424 continue; 2425 } else if (ch == perMill) { 2426 if (multiplier != 1) { 2427 throw new IllegalArgumentException ("Too many percent/per mille characters in pattern \"" + 2428 pattern + '"'); 2429 } 2430 multiplier = 1000; 2431 affix.append("'\u2030"); 2432 continue; 2433 } else if (ch == minus) { 2434 affix.append("'-"); 2435 continue; 2436 } 2437 } 2438 affix.append(ch); 2442 break; 2443 2444 case 1: 2445 if (j == 1) { 2451 ++phaseOneLength; 2452 } else { 2453 if (--phaseOneLength == 0) { 2454 phase = 2; 2455 affix = suffix; 2456 } 2457 continue; 2458 } 2459 2460 if (ch == digit) { 2470 if (zeroDigitCount > 0) { 2471 ++digitRightCount; 2472 } else { 2473 ++digitLeftCount; 2474 } 2475 if (groupingCount >= 0 && decimalPos < 0) { 2476 ++groupingCount; 2477 } 2478 } else if (ch == zeroDigit) { 2479 if (digitRightCount > 0) { 2480 throw new IllegalArgumentException ("Unexpected '0' in pattern \"" + 2481 pattern + '"'); 2482 } 2483 ++zeroDigitCount; 2484 if (groupingCount >= 0 && decimalPos < 0) { 2485 ++groupingCount; 2486 } 2487 } else if (ch == groupingSeparator) { 2488 groupingCount = 0; 2489 } else if (ch == decimalSeparator) { 2490 if (decimalPos >= 0) { 2491 throw new IllegalArgumentException ("Multiple decimal separators in pattern \"" + 2492 pattern + '"'); 2493 } 2494 decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; 2495 } else if (ch == exponent) { 2496 if (useExponentialNotation) { 2497 throw new IllegalArgumentException ("Multiple exponential " + 2498 "symbols in pattern \"" + pattern + '"'); 2499 } 2500 useExponentialNotation = true; 2501 minExponentDigits = 0; 2502 2503 while (++pos < pattern.length() && 2506 pattern.charAt(pos) == zeroDigit) { 2507 ++minExponentDigits; 2508 ++phaseOneLength; 2509 } 2510 2511 if ((digitLeftCount + zeroDigitCount) < 1 || 2512 minExponentDigits < 1) { 2513 throw new IllegalArgumentException ("Malformed exponential " + 2514 "pattern \"" + pattern + '"'); 2515 } 2516 2517 phase = 2; 2519 affix = suffix; 2520 --pos; 2521 continue; 2522 } else { 2523 phase = 2; 2524 affix = suffix; 2525 --pos; 2526 --phaseOneLength; 2527 continue; 2528 } 2529 break; 2530 } 2531 } 2532 2533 2545 if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) { 2546 int n = decimalPos; 2548 if (n == 0) { ++n; 2550 } 2551 digitRightCount = digitLeftCount - n; 2552 digitLeftCount = n - 1; 2553 zeroDigitCount = 1; 2554 } 2555 2556 if ((decimalPos < 0 && digitRightCount > 0) || 2558 (decimalPos >= 0 && (decimalPos < digitLeftCount || 2559 decimalPos > (digitLeftCount + zeroDigitCount))) || 2560 groupingCount == 0 || inQuote) { 2561 throw new IllegalArgumentException ("Malformed pattern \"" + 2562 pattern + '"'); 2563 } 2564 2565 if (j == 1) { 2566 posPrefixPattern = prefix.toString(); 2567 posSuffixPattern = suffix.toString(); 2568 negPrefixPattern = posPrefixPattern; negSuffixPattern = posSuffixPattern; 2570 int digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; 2571 2575 int effectiveDecimalPos = decimalPos >= 0 ? 2576 decimalPos : digitTotalCount; 2577 setMinimumIntegerDigits(effectiveDecimalPos - digitLeftCount); 2578 setMaximumIntegerDigits(useExponentialNotation ? 2579 digitLeftCount + getMinimumIntegerDigits() : 2580 MAXIMUM_INTEGER_DIGITS); 2581 setMaximumFractionDigits(decimalPos >= 0 ? 2582 (digitTotalCount - decimalPos) : 0); 2583 setMinimumFractionDigits(decimalPos >= 0 ? 2584 (digitLeftCount + zeroDigitCount - decimalPos) : 0); 2585 setGroupingUsed(groupingCount > 0); 2586 this.groupingSize = (groupingCount > 0) ? groupingCount : 0; 2587 this.multiplier = multiplier; 2588 setDecimalSeparatorAlwaysShown(decimalPos == 0 || 2589 decimalPos == digitTotalCount); 2590 } else { 2591 negPrefixPattern = prefix.toString(); 2592 negSuffixPattern = suffix.toString(); 2593 gotNegative = true; 2594 } 2595 } 2596 2597 if (pattern.length() == 0) { 2598 posPrefixPattern = posSuffixPattern = ""; 2599 setMinimumIntegerDigits(0); 2600 setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS); 2601 setMinimumFractionDigits(0); 2602 setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS); 2603 } 2604 2605 if (!gotNegative || 2609 (negPrefixPattern.equals(posPrefixPattern) 2610 && negSuffixPattern.equals(posSuffixPattern))) { 2611 negSuffixPattern = posSuffixPattern; 2612 negPrefixPattern = "'-" + posPrefixPattern; 2613 } 2614 2615 expandAffixes(); 2616 } 2617 2618 2626 public void setMaximumIntegerDigits(int newValue) { 2627 maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS); 2628 super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 2629 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits); 2630 if (minimumIntegerDigits > maximumIntegerDigits) { 2631 minimumIntegerDigits = maximumIntegerDigits; 2632 super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 2633 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits); 2634 } 2635 } 2636 2637 2645 public void setMinimumIntegerDigits(int newValue) { 2646 minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS); 2647 super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 2648 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits); 2649 if (minimumIntegerDigits > maximumIntegerDigits) { 2650 maximumIntegerDigits = minimumIntegerDigits; 2651 super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ? 2652 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits); 2653 } 2654 } 2655 2656 2664 public void setMaximumFractionDigits(int newValue) { 2665 maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS); 2666 super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 2667 DOUBLE_FRACTION_DIGITS : maximumFractionDigits); 2668 if (minimumFractionDigits > maximumFractionDigits) { 2669 minimumFractionDigits = maximumFractionDigits; 2670 super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 2671 DOUBLE_FRACTION_DIGITS : minimumFractionDigits); 2672 } 2673 } 2674 2675 2683 public void setMinimumFractionDigits(int newValue) { 2684 minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS); 2685 super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 2686 DOUBLE_FRACTION_DIGITS : minimumFractionDigits); 2687 if (minimumFractionDigits > maximumFractionDigits) { 2688 maximumFractionDigits = minimumFractionDigits; 2689 super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ? 2690 DOUBLE_FRACTION_DIGITS : maximumFractionDigits); 2691 } 2692 } 2693 2694 2702 public int getMaximumIntegerDigits() { 2703 return maximumIntegerDigits; 2704 } 2705 2706 2714 public int getMinimumIntegerDigits() { 2715 return minimumIntegerDigits; 2716 } 2717 2718 2726 public int getMaximumFractionDigits() { 2727 return maximumFractionDigits; 2728 } 2729 2730 2738 public int getMinimumFractionDigits() { 2739 return minimumFractionDigits; 2740 } 2741 2742 2752 public Currency getCurrency() { 2753 return symbols.getCurrency(); 2754 } 2755 2756 2768 public void setCurrency(Currency currency) { 2769 if (currency != symbols.getCurrency()) { 2770 symbols.setCurrency(currency); 2771 if (isCurrencyFormat) { 2772 expandAffixes(); 2773 } 2774 } 2775 } 2776 2777 2781 void adjustForCurrencyDefaultFractionDigits() { 2782 Currency currency = symbols.getCurrency(); 2783 if (currency == null) { 2784 try { 2785 currency = Currency.getInstance(symbols.getInternationalCurrencySymbol()); 2786 } catch (IllegalArgumentException e) { 2787 } 2788 } 2789 if (currency != null) { 2790 int digits = currency.getDefaultFractionDigits(); 2791 if (digits != -1) { 2792 int oldMinDigits = getMinimumFractionDigits(); 2793 if (oldMinDigits == getMaximumFractionDigits()) { 2796 setMinimumFractionDigits(digits); 2797 setMaximumFractionDigits(digits); 2798 } else { 2799 setMinimumFractionDigits(Math.min(digits, oldMinDigits)); 2800 setMaximumFractionDigits(digits); 2801 } 2802 } 2803 } 2804 } 2805 2806 2845 private void readObject(ObjectInputStream stream) 2846 throws IOException , ClassNotFoundException 2847 { 2848 stream.defaultReadObject(); 2849 2850 if (super.getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS || 2854 super.getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS) { 2855 throw new InvalidObjectException ("Digit count out of range"); 2856 } 2857 if (serialVersionOnStream < 3) { 2858 setMaximumIntegerDigits(super.getMaximumIntegerDigits()); 2859 setMinimumIntegerDigits(super.getMinimumIntegerDigits()); 2860 setMaximumFractionDigits(super.getMaximumFractionDigits()); 2861 setMinimumFractionDigits(super.getMinimumFractionDigits()); 2862 } 2863 if (serialVersionOnStream < 1) { 2864 useExponentialNotation = false; 2866 } 2867 serialVersionOnStream = currentSerialVersion; 2868 digitList = new DigitList (); 2869 } 2870 2871 2875 private transient DigitList digitList = new DigitList (); 2876 2877 2883 private String positivePrefix = ""; 2884 2885 2892 private String positiveSuffix = ""; 2893 2894 2900 private String negativePrefix = "-"; 2901 2902 2909 private String negativeSuffix = ""; 2910 2911 2926 private String posPrefixPattern; 2927 2928 2937 private String posSuffixPattern; 2938 2939 2948 private String negPrefixPattern; 2949 2950 2959 private String negSuffixPattern; 2960 2961 2967 private int multiplier = 1; 2968 2969 2978 private byte groupingSize = 3; 2980 2987 private boolean decimalSeparatorAlwaysShown = false; 2988 2989 2996 private boolean parseBigDecimal = false; 2997 2998 2999 3003 private transient boolean isCurrencyFormat = false; 3004 3005 3014 private DecimalFormatSymbols symbols = null; 3016 3023 private boolean useExponentialNotation; 3025 3030 private transient FieldPosition [] positivePrefixFieldPositions; 3031 3032 3037 private transient FieldPosition [] positiveSuffixFieldPositions; 3038 3039 3044 private transient FieldPosition [] negativePrefixFieldPositions; 3045 3046 3051 private transient FieldPosition [] negativeSuffixFieldPositions; 3052 3053 3061 private byte minExponentDigits; 3063 3073 private int maximumIntegerDigits = super.getMaximumIntegerDigits(); 3074 3075 3085 private int minimumIntegerDigits = super.getMinimumIntegerDigits(); 3086 3087 3097 private int maximumFractionDigits = super.getMaximumFractionDigits(); 3098 3099 3109 private int minimumFractionDigits = super.getMinimumFractionDigits(); 3110 3111 3113 static final int currentSerialVersion = 3; 3114 3115 3136 private int serialVersionOnStream = currentSerialVersion; 3137 3138 3142 private static final char PATTERN_ZERO_DIGIT = '0'; 3144 private static final char PATTERN_GROUPING_SEPARATOR = ','; 3145 private static final char PATTERN_DECIMAL_SEPARATOR = '.'; 3146 private static final char PATTERN_PER_MILLE = '\u2030'; 3147 private static final char PATTERN_PERCENT = '%'; 3148 private static final char PATTERN_DIGIT = '#'; 3149 private static final char PATTERN_SEPARATOR = ';'; 3150 private static final char PATTERN_EXPONENT = 'E'; 3151 private static final char PATTERN_MINUS = '-'; 3152 3153 3162 private static final char CURRENCY_SIGN = '\u00A4'; 3163 3164 private static final char QUOTE = '\''; 3165 3166 private static FieldPosition [] EmptyFieldPositionArray = new FieldPosition [0]; 3167 3168 static final int DOUBLE_INTEGER_DIGITS = 309; 3170 static final int DOUBLE_FRACTION_DIGITS = 340; 3171 3172 static final int MAXIMUM_INTEGER_DIGITS = Integer.MAX_VALUE; 3174 static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE; 3175 3176 static final long serialVersionUID = 864413376551465018L; 3178 3179 3182 private static Hashtable cachedLocaleData = new Hashtable (3); 3183} 3184 | Popular Tags |