You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gh...@apache.org on 2006/04/11 12:02:26 UTC
svn commit: r393171 - in
/incubator/harmony/enhanced/classlib/trunk/modules/text: make/common/
src/main/java/java/text/ src/test/java/org/apache/harmony/tests/java/text/
Author: gharley
Date: Tue Apr 11 03:02:16 2006
New Revision: 393171
URL: http://svn.apache.org/viewcvs?rev=393171&view=rev
Log:
Backing out HARMONY-205 changes pending investigation of test failures in LUNI, SQL, Security etc.
Removed:
incubator/harmony/enhanced/classlib/trunk/modules/text/src/test/java/org/apache/harmony/tests/java/text/DecimalFormatTest.java
Modified:
incubator/harmony/enhanced/classlib/trunk/modules/text/make/common/build.xml
incubator/harmony/enhanced/classlib/trunk/modules/text/src/main/java/java/text/DecimalFormat.java
incubator/harmony/enhanced/classlib/trunk/modules/text/src/test/java/org/apache/harmony/tests/java/text/AllTests.java
Modified: incubator/harmony/enhanced/classlib/trunk/modules/text/make/common/build.xml
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/text/make/common/build.xml?rev=393171&r1=393170&r2=393171&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/text/make/common/build.xml (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/text/make/common/build.xml Tue Apr 11 03:02:16 2006
@@ -95,7 +95,7 @@
<exclude name="**/ChoiceFormatTest.java"/>
<exclude name="**/CollationKeyTest.java"/>
<exclude name="**/CollatorTest.java"/>
- <exclude name="tests/api/java/text/DecimalFormatTest.java"/>
+ <exclude name="**/DecimalFormatTest.java"/>
<exclude name="**/MessageFormatTest.java"/>
<exclude name="**/NumberFormatTest.java"/>
<exclude name="**/SimpleDateFormatTest.java"/>
Modified: incubator/harmony/enhanced/classlib/trunk/modules/text/src/main/java/java/text/DecimalFormat.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/text/src/main/java/java/text/DecimalFormat.java?rev=393171&r1=393170&r2=393171&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/text/src/main/java/java/text/DecimalFormat.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/text/src/main/java/java/text/DecimalFormat.java Tue Apr 11 03:02:16 2006
@@ -1,4 +1,4 @@
-/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,15 +15,15 @@
package java.text;
+
import java.io.IOException;
+import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.math.BigDecimal;
-import java.math.BigInteger;
import java.util.Currency;
import java.util.Locale;
+import java.util.Vector;
-import org.apache.harmony.luni.util.NotYetImplementedException;
+import org.apache.harmony.luni.util.Msg;
/**
* DecimalFormat is used to format and parse numbers, both integers and
@@ -32,17 +32,43 @@
*/
public class DecimalFormat extends NumberFormat {
- static final long serialVersionUID = 864413376551465018L;
+ private static final long serialVersionUID = 864413376551465018L;
+
+ private static final String patternChars = "0#.,;%\u2030E";
+
+ private static final char CURRENCY_SYMBOL = '\u00a4';
+
+ private static final int DOUBLE_INTEGER_DIGITS = 309;
+
+ private static final int DOUBLE_FRACTION_DIGITS = 340;
+
+ private byte groupingSize = 3;
- private boolean parseBigDecimal = false;
+ private int multiplier = 1;
+
+ private String positivePrefix = "", positiveSuffix = "",
+ negativePrefix = "-", negativeSuffix = "";
+
+ private String posPrefixPattern, posSuffixPattern, negPrefixPattern,
+ negSuffixPattern;
+
+ private boolean decimalSeparatorAlwaysShown = false;
+
+ transient private boolean posPrefixMonetary = false,
+ posSuffixMonetary = false, negPrefixMonetary = false,
+ negSuffixMonetary = false;
private DecimalFormatSymbols symbols;
- private transient com.ibm.icu.text.DecimalFormat dform;
+ private boolean useExponentialNotation = false;
+
+ private byte minExponentDigits;
+
+ private int serialVersionOnStream = 2;
- private transient com.ibm.icu.text.DecimalFormatSymbols icuSymbols;
+ transient private char zero;
- static final int currentSerialVersion = 3;
+ private static final double log10 = Math.log(10);
/**
* Constructs a new DecimalFormat for formatting and parsing numbers for the
@@ -63,7 +89,9 @@
* when the pattern cannot be parsed
*/
public DecimalFormat(String pattern) {
- this(pattern, new DecimalFormatSymbols());
+ symbols = new DecimalFormatSymbols();
+ zero = symbols.getZeroDigit();
+ applyPattern(pattern);
}
/**
@@ -79,45 +107,9 @@
* when the pattern cannot be parsed
*/
public DecimalFormat(String pattern, DecimalFormatSymbols value) {
- dform = (com.ibm.icu.text.DecimalFormat) com.ibm.icu.text.NumberFormat
- .getInstance();
+ symbols = (DecimalFormatSymbols) value.clone();
+ zero = symbols.getZeroDigit();
applyPattern(pattern);
- symbols = value;
-
- icuSymbols = adapt2ICU(symbols);
-
- dform.setDecimalFormatSymbols(icuSymbols);
- setMaximumFractionDigits(dform.getMaximumFractionDigits());
- setMinimumFractionDigits(dform.getMinimumFractionDigits());
- setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
- setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
-
-
- }
-
- private com.ibm.icu.text.DecimalFormatSymbols adapt2ICU(
- DecimalFormatSymbols symbols) {
- com.ibm.icu.text.DecimalFormatSymbols icuSymbols = new com.ibm.icu.text.DecimalFormatSymbols();
- String currencyCode = symbols.getCurrency().getCurrencyCode();
- icuSymbols.setCurrency(com.ibm.icu.util.Currency
- .getInstance(currencyCode));
- icuSymbols.setCurrencySymbol(symbols.getCurrencySymbol());
- icuSymbols.setDecimalSeparator(symbols.getDecimalSeparator());
- icuSymbols.setDigit(symbols.getDigit());
- icuSymbols.setGroupingSeparator(symbols.getGroupingSeparator());
- icuSymbols.setInfinity(symbols.getInfinity());
- icuSymbols.setInternationalCurrencySymbol(symbols
- .getInternationalCurrencySymbol());
- icuSymbols.setMinusSign(symbols.getMinusSign());
- icuSymbols.setMonetaryDecimalSeparator(symbols
- .getMonetaryDecimalSeparator());
- icuSymbols.setNaN(symbols.getNaN());
- icuSymbols.setPatternSeparator(symbols.getPatternSeparator());
- icuSymbols.setPercent(symbols.getPercent());
- icuSymbols.setPerMill(symbols.getPerMill());
- icuSymbols.setZeroDigit(symbols.getZeroDigit());
-
- return icuSymbols;
}
/**
@@ -131,7 +123,8 @@
* when the pattern cannot be parsed
*/
public void applyLocalizedPattern(String pattern) {
- dform.applyLocalizedPattern(pattern);
+ applyPattern(convertPattern(pattern, symbols.getLocalPatternChars(),
+ patternChars, false));
}
/**
@@ -145,8 +138,184 @@
* when the pattern cannot be parsed
*/
public void applyPattern(String pattern) {
+ if (pattern.length() == 0)
+ return;
+ int next, grouping = 0, intCount = 0, minInt = 0, minFraction = 0, maxFraction = 0, localMultiplier = 1, minExponent = 0;
+ boolean inPrefix = true, countGrouping = false, exponent = false, fraction = false, negative = false, inSuffix = false;
+ StringBuffer buffer = new StringBuffer();
+ String prefix = "", suffix = "", negPrefix = "", negSuffix = "", format = null;
+ boolean quote = false, lastQuote = false;
+ final int patternLength = pattern.length();
+ for (int i = 0; i < patternLength; i++) {
+ next = (pattern.charAt(i));
+ if (!quote
+ && ("0#,.".indexOf(next) != -1 || (!exponent && !inPrefix
+ && !inSuffix && next == 'E'))) {
+ if (inPrefix) {
+ if (negative)
+ negPrefix = buffer.toString();
+ else
+ prefix = buffer.toString();
+ buffer.setLength(0);
+ inPrefix = false;
+ }
+ if (inSuffix)
+ throw new IllegalArgumentException(Msg.getString("K0014",
+ String.valueOf((char) next), pattern));
+ buffer.append((char) next);
+ if (next == 'E')
+ exponent = true;
+ if (negative)
+ continue;
+ switch (next) {
+ case '0':
+ if (countGrouping)
+ grouping++;
+ if (exponent)
+ minExponent++;
+ else {
+ if (maxFraction > 0)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0015", String.valueOf((char) next),
+ pattern));
+ if (fraction)
+ minFraction++;
+ else
+ minInt++;
+ }
+ break;
+ case '#':
+ if ((!fraction && minInt > 0) || exponent)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0016", String.valueOf((char) next), pattern));
+ if (countGrouping)
+ grouping++;
+ if (fraction)
+ maxFraction++;
+ else
+ intCount++;
+ break;
+ case ',':
+ if (fraction || exponent)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0016", String.valueOf((char) next), pattern));
+ grouping = 0;
+ countGrouping = true;
+ break;
+ case '.':
+ if (fraction || exponent)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0016", String.valueOf((char) next), pattern));
+ countGrouping = false;
+ fraction = true;
+ break;
+ case 'E':
+ countGrouping = false;
+ break;
+ }
+ } else {
+ if (!inPrefix && !inSuffix) {
+ if (!negative)
+ format = buffer.toString();
+ buffer.setLength(0);
+ }
+ if (!inPrefix)
+ inSuffix = true;
+ if (next == '\'') {
+ if (lastQuote)
+ buffer.append('\'');
+ quote = !quote;
+ lastQuote = true;
+ } else {
+ lastQuote = false;
+ if (next == ';' && !quote) {
+ if (format == null || format.length() == 0)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0017", String.valueOf((char) next),
+ pattern));
+ if (exponent && minExponent == 0)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0018", pattern));
+ suffix = buffer.toString();
+ buffer.setLength(0);
+ negative = inPrefix = true;
+ inSuffix = exponent = false;
+ continue;
+ }
+ if (!negative
+ && (next == symbols.getPercent() || next == symbols
+ .getPerMill()) && !quote) {
+ if (localMultiplier != 1)
+ throw new IllegalArgumentException(Msg.getString(
+ "K0016", String.valueOf((char) next),
+ pattern));
+ localMultiplier = next == symbols.getPercent() ? 100
+ : 1000;
+ }
+ buffer.append((char) next);
+ }
+ }
+ }
+ if (quote)
+ throw new IllegalArgumentException(Msg.getString("K0019", pattern));
+ if (countGrouping && grouping == 0)
+ throw new IllegalArgumentException(Msg.getString("K001a", pattern));
+ if (!negative && exponent && minExponent == 0)
+ throw new IllegalArgumentException(Msg.getString("K0018", pattern));
+ if (minExponent > 0
+ && intCount + minInt + minFraction + maxFraction == 0)
+ throw new IllegalArgumentException(Msg.getString("K001b", pattern));
+ if (inPrefix) {
+ if (negative)
+ negPrefix = buffer.toString();
+ else
+ prefix = buffer.toString();
+ }
+ if (inSuffix) {
+ if (negative)
+ negSuffix = buffer.toString();
+ else
+ suffix = buffer.toString();
+ }
- dform.applyPattern(pattern);
+ maxFraction += minFraction;
+ if (fraction && minFraction == 0 && minInt == 0 && intCount > 0) {
+ minInt = 1;
+ intCount--;
+ } else if (maxFraction > 0 && minInt + intCount == 0
+ && minFraction == 0)
+ minFraction = 1;
+ useExponentialNotation = minExponent > 0;
+ if (useExponentialNotation) {
+ setMaximumIntegerDigits(intCount + minInt);
+ } else
+ setMaximumIntegerDigits(Integer.MAX_VALUE);
+ setMinimumIntegerDigits(minInt);
+ setMaximumFractionDigits(maxFraction);
+ setMinimumFractionDigits(minFraction);
+ setGroupingSize(grouping);
+ setGroupingUsed(grouping > 0);
+ setPositivePrefix(prefix.toString());
+ setPositiveSuffix(suffix.toString());
+ posPrefixMonetary = positivePrefix.indexOf(CURRENCY_SYMBOL) > -1;
+ posPrefixPattern = expandAffix(positivePrefix);
+ posSuffixMonetary = positiveSuffix.indexOf(CURRENCY_SYMBOL) > -1;
+ posSuffixPattern = expandAffix(positiveSuffix);
+ minExponentDigits = minExponent > Byte.MAX_VALUE ? Byte.MAX_VALUE
+ : (byte) minExponent;
+ if (!negative) {
+ negPrefix = symbols.getMinusSign() + prefix;
+ negSuffix = suffix;
+ }
+ setNegativePrefix(negPrefix);
+ setNegativeSuffix(negSuffix);
+ negPrefixMonetary = negPrefix.indexOf(CURRENCY_SYMBOL) > -1;
+ negPrefixPattern = expandAffix(negPrefix);
+ negSuffixMonetary = negSuffix.indexOf(CURRENCY_SYMBOL) > -1;
+ negSuffixPattern = expandAffix(negSuffix);
+ setDecimalSeparatorAlwaysShown(fraction
+ && (minInt + intCount == 0 || minFraction + maxFraction == 0));
+ setMultiplier(localMultiplier);
}
/**
@@ -159,11 +328,32 @@
*/
public Object clone() {
DecimalFormat clone = (DecimalFormat) super.clone();
- clone.dform = (com.ibm.icu.text.DecimalFormat) dform.clone();
clone.symbols = (DecimalFormatSymbols) symbols.clone();
return clone;
}
+ private String convertCurrencySymbols(String value) {
+ StringBuffer output = null;
+ for (int i = 0; i < value.length(); i++) {
+ char next;
+ if ((next = value.charAt(i)) == CURRENCY_SYMBOL) {
+ if (output == null)
+ output = new StringBuffer(value.substring(0, i));
+ if (i + 1 < value.length()
+ && value.charAt(i + 1) == CURRENCY_SYMBOL) {
+ i++;
+ output.append(symbols.getInternationalCurrencySymbol());
+ } else {
+ output.append(symbols.getCurrencySymbol());
+ }
+ } else if (output != null)
+ output.append(next);
+ }
+ if (output == null)
+ return value;
+ return output.toString();
+ }
+
/**
* Compares the specified object to this DecimalFormat and answer if they
* are equal. The object must be an instance of DecimalFormat with the same
@@ -177,15 +367,26 @@
* @see #hashCode
*/
public boolean equals(Object object) {
- if (this == object) {
+ if (this == object)
return true;
- }
- if (!(object instanceof DecimalFormat)) {
+ if (!(object instanceof DecimalFormat))
return false;
- }
DecimalFormat format = (DecimalFormat) object;
- return (this.dform == null ? format.dform == null : this.dform
- .equals(format.dform));
+ return super.equals(object)
+ && symbols.equals(format.symbols)
+ && groupingSize == format.groupingSize
+ && multiplier == format.multiplier
+ && positivePrefix.equals(format.positivePrefix)
+ && positiveSuffix.equals(format.positiveSuffix)
+ && negativePrefix.equals(format.negativePrefix)
+ && negativeSuffix.equals(format.negativeSuffix)
+ && decimalSeparatorAlwaysShown == format.decimalSeparatorAlwaysShown
+ && isCurrency() == format.isCurrency();
+ }
+
+ private Number error(ParsePosition position, int offset) {
+ position.setErrorIndex(offset);
+ return null;
}
/**
@@ -202,7 +403,33 @@
* when the object cannot be formatted by this Format
*/
public AttributedCharacterIterator formatToCharacterIterator(Object object) {
- return dform.formatToCharacterIterator(object);
+ if (!(object instanceof Number))
+ throw new IllegalArgumentException();
+
+ StringBuffer buffer = new StringBuffer();
+ Vector fields = new Vector();
+
+ // format the number, and find fields
+ double dv = ((Number) object).doubleValue();
+ long lv = ((Number) object).longValue();
+ if (dv == lv)
+ formatImpl(lv, buffer, new FieldPosition(0), fields);
+ else
+ formatImpl(dv, buffer, new FieldPosition(0), fields);
+
+ // create an AttributedString with the formatted buffer
+ AttributedString as = new AttributedString(buffer.toString());
+
+ // add NumberFormat field attributes to the AttributedString
+ for (int i = 0; i < fields.size(); i++) {
+ FieldPosition pos = (FieldPosition) fields.elementAt(i);
+ Format.Field attribute = pos.getFieldAttribute();
+ as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
+ .getEndIndex());
+ }
+
+ // return the CharacterIterator from AttributedString
+ return as.getIterator();
}
/**
@@ -221,9 +448,246 @@
*/
public StringBuffer format(double value, StringBuffer buffer,
FieldPosition position) {
- return dform.format(value, buffer, position);
+ return formatImpl(value, buffer, position, null);
}
+ private StringBuffer formatImpl(double value, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ if (multiplier != 1)
+ value *= multiplier;
+
+ position.clear();
+ if (Double.isNaN(value))
+ return buffer.append(symbols.getNaN());
+
+ long bits = Double.doubleToLongBits(value);
+ // SIGN or CURRENCY fields
+ String prefix = (bits < 0) ? getNegativePrefix() : getPositivePrefix();
+ formatPrefixSuffix(prefix, buffer, position, fields);
+
+ // INTEGER field begins
+ FieldPosition positionInteger = null;
+ positionInteger = new FieldPosition(Field.INTEGER);
+ handleIntegerBegin(buffer.length(), position, fields, positionInteger);
+
+ if (Double.isInfinite(value)) {
+ buffer.append(symbols.getInfinity());
+
+ // INTEGER field ends
+ handleIntegerEnd(buffer.length(), position, fields, positionInteger);
+ } else {
+ double abs = value < 0 ? -value : value;
+
+ boolean fixed = false;
+ int scale = 0, exponent = 0;
+ int minFract = 0, maxFract = 0;
+ if (useExponentialNotation) {
+ exponent = scale(abs);
+ minFract = getMinimumIntegerDigits()
+ + getMinimumFractionDigits();
+ fixed = getMinimumIntegerDigits() == getMaximumIntegerDigits();
+ if (fixed) {
+ minFract -= getMinimumIntegerDigits();
+ scale = getMinimumIntegerDigits() - 1;
+ if (value != 0)
+ exponent -= scale;
+ } else {
+ scale = exponent % getMaximumIntegerDigits();
+ if (exponent < -1
+ && scale + getMaximumIntegerDigits() < getMaximumIntegerDigits())
+ scale += getMaximumIntegerDigits();
+ if (getMinimumIntegerDigits() == 0)
+ scale--;
+ if (value != 0)
+ exponent -= scale;
+ if (scale >= 0)
+ minFract -= scale + 1;
+ }
+ if (exponent != 0)
+ abs /= Math.pow(10.0, exponent);
+ maxFract = getMaximumIntegerDigits()
+ + getMaximumFractionDigits();
+ if (scale >= 0)
+ maxFract -= scale + 1;
+ } else {
+ scale = scale(abs);
+ minFract = getMinimumFractionDigits();
+ maxFract = getMaximumFractionDigits();
+ }
+ if (-maxFract - 1 >= (scale - 16)) {
+ // Round decimal digits
+ abs += Math.pow(10.0, -maxFract - 1) * 5;
+ }
+
+ // In case rounding changed the scale
+ int checkScale = scale(abs);
+ if (checkScale > scale) {
+ // Rounding changed the scale
+ if (useExponentialNotation) {
+ if (fixed || getMinimumIntegerDigits() == 0) {
+ abs /= 10.0;
+ exponent++;
+ } else {
+ if (scale + 1 == getMaximumIntegerDigits()
+ ||
+ // catch .1E0 instead of 100E-3 case
+ (exponent + getMaximumIntegerDigits() == 0 && scale + 2 == getMaximumIntegerDigits())) {
+ exponent += getMaximumIntegerDigits();
+ abs /= Math.pow(10.0, getMaximumIntegerDigits());
+ int adjust;
+ if (exponent == 0)
+ adjust = -1;
+ else
+ adjust = 0;
+ minFract += scale - adjust;
+ maxFract += scale - adjust;
+ scale = adjust;
+ } else {
+ scale++;
+ minFract--;
+ maxFract--;
+ }
+ }
+ } else
+ scale = checkScale;
+ }
+
+ long digits;
+ int shift = 0, dLength;
+ String sValue = Double.toString(abs);
+ dLength = sValue.lastIndexOf('E');
+ if (dLength > -1)
+ shift = Integer.parseInt(sValue.substring(dLength + 1));
+ else
+ dLength = sValue.length();
+ int index = sValue.indexOf('.');
+ if (index > -1) {
+ String fValue = sValue.substring(index + 1, dLength);
+ String iValue = sValue.substring(0, index);
+ if (fValue.equals("0")) {
+ sValue = iValue;
+ dLength -= 2;
+ } else {
+ shift -= fValue.length();
+ if (iValue.equals("0")) {
+ int i = 0;
+ while (fValue.charAt(i) == '0')
+ i++;
+ sValue = fValue.substring(i);
+ dLength -= i + 2;
+ } else {
+ sValue = iValue + fValue;
+ dLength--;
+ }
+ }
+ } else
+ sValue = sValue.substring(0, dLength);
+ digits = Long.parseLong(sValue);
+
+ int iLength = dLength;
+ long number = digits;
+ if (shift < 0) {
+ if (-shift < dLength) {
+ iLength = dLength + shift;
+ long pow = intPow(-shift);
+ number /= pow;
+ digits -= number * pow;
+ dLength = -shift;
+ } else {
+ number = 0;
+ iLength = 1;
+ }
+ } else {
+ iLength += shift;
+ digits = 0;
+ dLength = 0;
+ }
+ if (maxFract != 0 && maxFract < dLength) {
+ long pow = intPow(dLength - maxFract);
+ digits /= pow;
+ shift += dLength - maxFract;
+ dLength = maxFract;
+ }
+
+ int length = buffer.length();
+ StringBuffer output = new StringBuffer();
+
+ if (scale < 0 && !useExponentialNotation)
+ formatInteger("0", buffer, position, fields);
+ else {
+ output.append(Long.toString(number));
+ for (int i = output.length(); i < iLength; i++)
+ output.append('0');
+ if (useExponentialNotation) {
+ for (int i = 0; i <= scale; i++) {
+ if (i >= output.length())
+ buffer.append(zero);
+ else
+ buffer
+ .append((char) (zero + (output.charAt(i) - '0')));
+ }
+ } else
+ formatInteger(output.toString(), buffer, position, fields);
+ }
+
+ if (maxFract == 0) {
+ if (length == buffer.length())
+ buffer.append(zero);
+ // INTEGER field ends
+ handleIntegerEnd(buffer.length(), position, fields,
+ positionInteger);
+
+ // format DECIMAL_SEPARATOR field
+ formatFraction(new StringBuffer(), buffer, position, fields);
+ } else {
+ output.setLength(0);
+ int lastDigit = 0, leading = -shift - dLength;
+ if (digits > 0 && maxFract > leading) {
+ String print = Long.toString(digits);
+ if (dLength > print.length())
+ leading += dLength - print.length();
+ for (int i = 0; i < leading; i++)
+ output.append(zero);
+ for (int i = leading; i < maxFract; i++) {
+ int digit;
+ if (i - leading >= print.length())
+ digit = 0;
+ else
+ digit = print.charAt(i - leading) - '0';
+ output.append((char) (zero + digit));
+ if (digit > 0)
+ lastDigit = output.length();
+ }
+ }
+ if (output.length() < minFract) {
+ for (int i = output.length(); i < minFract; i++)
+ output.append(zero);
+ } else {
+ output.setLength(lastDigit < minFract ? minFract
+ : lastDigit);
+ }
+ if (output.length() == 0 && length == buffer.length())
+ buffer.append(zero);
+
+ // INTEGER Field ends
+ handleIntegerEnd(buffer.length(), position, fields,
+ positionInteger);
+
+ // format DECIMAL_SEPARATOR and FRACTION fields
+ formatFraction(output, buffer, position, fields);
+ }
+
+ if (useExponentialNotation)
+ formatExponent(exponent, buffer, position, fields);
+ }
+
+ // handle SIGN, CURRENCY, PERMILLE or PERCENT fields
+ String suffix = (bits < 0) ? getNegativeSuffix() : getPositiveSuffix();
+ formatPrefixSuffix(suffix, buffer, position, fields);
+
+ return buffer;
+}
+
/**
* Formats the long value into the specified StringBuffer using the pattern
* of this DecimalFormat. If the field specified by the FieldPosition is
@@ -240,21 +704,389 @@
*/
public StringBuffer format(long value, StringBuffer buffer,
FieldPosition position) {
- return dform.format(value, buffer, position);
+ return formatImpl(value, buffer, position, null);
}
- public final StringBuffer format(Object number, StringBuffer toAppendTo,
- FieldPosition pos) {
- if (!(number instanceof Number)) {
- throw new IllegalArgumentException();
+ private StringBuffer formatImpl(long value, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ if (multiplier != 1) {
+ int sign = 1;
+ if (value < 0)
+ sign *= -1;
+ if (multiplier < 0)
+ sign *= -1;
+ long oldValue = value;
+ value *= multiplier;
+ if ((sign > 0 && oldValue >= value)
+ || (sign < 0 && oldValue <= value))
+ return formatImpl((double) oldValue, buffer, position, fields);
+
+ // Check for large overflows missed by the previous check
+ double result = (double) value * multiplier;
+ if (result > Long.MAX_VALUE || result < Long.MIN_VALUE)
+ return formatImpl((double) value, buffer, position, fields);
+ }
+
+ // SIGN or CURRENCY fields
+ String prefix = (value < 0) ? getNegativePrefix() : getPositivePrefix();
+ formatPrefixSuffix(prefix, buffer, position, fields);
+
+ // INTEGER field begins
+ FieldPosition positionInteger = null;
+ positionInteger = new FieldPosition(Field.INTEGER);
+ handleIntegerBegin(buffer.length(), position, fields, positionInteger);
+
+ int outLength = buffer.length();
+ String digits = Long.toString(value);
+
+ int exponent = 0, scale = 0, minFract = 0;
+ if (useExponentialNotation) {
+ if (value < 0)
+ digits = digits.substring(1, digits.length());
+ int length = digits.length();
+ minFract = getMinimumIntegerDigits() + getMinimumFractionDigits();
+ exponent = length - 1;
+
+ boolean fixed = getMinimumIntegerDigits() == getMaximumIntegerDigits();
+ if (fixed) {
+ minFract -= getMinimumIntegerDigits();
+ scale = getMinimumIntegerDigits() - 1;
+ if (value != 0)
+ exponent -= scale;
+ scale++;
+ } else {
+ scale = exponent % getMaximumIntegerDigits();
+ if (value != 0)
+ exponent -= scale;
+ if (getMinimumIntegerDigits() > 0)
+ scale++;
+ else if (value != 0)
+ exponent++;
+ minFract -= scale;
+ }
+ if (getMaximumIntegerDigits() + getMaximumFractionDigits() < length) {
+ int chop = length
+ - (getMaximumIntegerDigits() + getMaximumFractionDigits())
+ - 1;
+ for (int i = chop; --i >= 0;)
+ value /= 10;
+ // Round decimal digits
+ if (value < 0)
+ value -= 5;
+ else
+ value += 5;
+ digits = Long.toString(value);
+ if (value < 0)
+ digits = digits.substring(1, digits.length());
+
+ int remove = 1;
+ if (digits.length() > (length - chop)) {
+ // Rounding changed the scale
+ if (fixed || getMinimumIntegerDigits() == 0) {
+ remove++;
+ exponent++;
+ } else {
+ if (scale == getMaximumIntegerDigits()) {
+ exponent += getMaximumIntegerDigits();
+ remove += getMaximumIntegerDigits();
+ minFract += scale - 1;
+ scale = 1;
+ } else {
+ scale++;
+ minFract--;
+ }
+ }
+ }
+ digits = digits.substring(0, digits.length() - remove);
+ }
+ for (int i = 0; i < scale; i++) {
+ if (i >= digits.length())
+ buffer.append(zero);
+ else
+ buffer.append((char) (zero + (digits.charAt(i) - '0')));
+ }
+ } else
+ formatInteger(digits, buffer, position, fields);
+
+ // Always print a digit
+ if (!useExponentialNotation && outLength == buffer.length())
+ buffer.append(zero);
+
+ // INTEGER Field ends
+ handleIntegerEnd(buffer.length(), position, fields, positionInteger);
+
+ if (useExponentialNotation) {
+ StringBuffer output = new StringBuffer();
+ int lastDigit = 0;
+ for (int i = 0; i < digits.length() - scale; i++) {
+ int digit = digits.charAt(scale + i) - '0';
+ if (digit > 0)
+ lastDigit = i + 1;
+ output.append((char) (zero + digit));
+ }
+ for (int i = output.length(); i < minFract; i++)
+ output.append(zero);
+ output.setLength(lastDigit < minFract ? minFract : lastDigit);
+ formatFraction(output, buffer, position, fields);
+ } else {
+ StringBuffer output = new StringBuffer();
+ for (int i = 0; i < getMinimumFractionDigits(); i++)
+ output.append(zero);
+ formatFraction(output, buffer, position, fields);
+ }
+
+ if (useExponentialNotation)
+ formatExponent(exponent, buffer, position, fields);
+
+ // handle SIGN, CURRENCY, PERMILLE or PERCENT fields
+ String suffix = (value < 0) ? getNegativeSuffix() : getPositiveSuffix();
+ formatPrefixSuffix(suffix, buffer, position, fields);
+
+ return buffer;
+ }
+
+ private void formatPrefixSuffix(String fix, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ int beginIndex = buffer.length();
+ buffer.append(fix);
+
+ if (fix.length() > 0) {
+ DecimalFormatSymbols formatSymbols = getDecimalFormatSymbols();
+ String curSymbol = formatSymbols.getCurrencySymbol();
+
+ int index;
+ if ((index = fix.indexOf(curSymbol)) > -1)
+ handleField(Field.CURRENCY, beginIndex + index, beginIndex
+ + index + curSymbol.length(), position, fields);
+
+ if ((index = fix.indexOf(formatSymbols.getMinusSign())) > -1)
+ handleField(Field.SIGN, beginIndex + index, beginIndex + index
+ + 1, position, fields);
+
+ if ((index = fix.indexOf(formatSymbols.getPercent())) > -1)
+ handleField(Field.PERCENT, beginIndex + index, beginIndex
+ + index + 1, position, fields);
+
+ if ((index = fix.indexOf(formatSymbols.getPerMill())) > -1)
+ handleField(Field.PERMILLE, beginIndex + index, beginIndex
+ + index + 1, position, fields);
+ }
+ }
+
+ private void formatInteger(String output, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ int offset = 0;
+ int total = output.length();
+
+ if (output.charAt(0) == '-') {
+ offset = 1;
+ total--;
+ }
+
+ boolean firstOccurrenceFound = false;
+ int groupSize = getGroupingSize();
+ if (!isGroupingUsed())
+ groupSize = 0;
+ if (getMinimumIntegerDigits() > total) {
+ int extra = getMinimumIntegerDigits() - total;
+ total = getMinimumIntegerDigits();
+ for (int i = 0; i < extra; i++) {
+ buffer.append(zero);
+ total--;
+ if (groupSize > 0 && total > 0 && total % groupSize == 0) {
+ buffer.append(symbols.getGroupingSeparator());
+ int index = buffer.length();
+ if (fields != null) {
+ addToFields(fields, Field.GROUPING_SEPARATOR,
+ index - 1, index);
+ } else {
+ if (!firstOccurrenceFound
+ && position.getFieldAttribute() == Field.GROUPING_SEPARATOR) {
+ position.setBeginIndex(index - 1);
+ position.setEndIndex(index);
+ firstOccurrenceFound = true;
+ }
+ }
+ }
+
+ }
+ }
+
+ if (total > getMaximumIntegerDigits()) {
+ offset += total - getMaximumIntegerDigits();
+ total = getMaximumIntegerDigits();
}
- if (toAppendTo == null || pos == null) {
- throw new NullPointerException();
+
+ if (getMinimumIntegerDigits() == 0 && total == 1
+ && output.charAt(offset) == '0')
+ return;
+
+ for (int i = offset; i < output.length(); i++) {
+ buffer.append((char) (zero + (output.charAt(i) - '0')));
+ total--;
+ if (groupSize > 0 && total > 0 && total % groupSize == 0) {
+ buffer.append(symbols.getGroupingSeparator());
+ int index = buffer.length();
+ if (fields != null) {
+ addToFields(fields, Field.GROUPING_SEPARATOR, index - 1,
+ index);
+ } else {
+ if (!firstOccurrenceFound
+ && position.getFieldAttribute() == Field.GROUPING_SEPARATOR) {
+ position.setBeginIndex(index - 1);
+ position.setEndIndex(index);
+ firstOccurrenceFound = true;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Appends decimal seperator and fraction fields to the buffer, and to the
+ * fields vector if needed.
+ *
+ * Sets the begin and end index of the position if fields vector is null,
+ * and position has a DECIMAL_SEPARATOR or FRACTION field.
+ *
+ * @param fraction
+ * @param buffer
+ * @param position
+ * @param fields
+ */
+ private void formatFraction(StringBuffer fraction, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ int index;
+ int len = fraction.length();
+ if (isDecimalSeparatorAlwaysShown() || len > 0) {
+ // DECIMAL_SEPERATOR field
+ buffer.append(getDecimalSeparator());
+ index = buffer.length();
+ handleField(Field.DECIMAL_SEPARATOR, index - 1, index, position,
+ fields);
+ }
+
+ if (len > 0) {
+ // FRACTION field
+ buffer.append(fraction);
+ index = buffer.length();
+ if (fields != null)
+ addToFields(fields, Field.FRACTION, index - len, index);
+ else {
+ if (position.getFieldAttribute() == Field.FRACTION
+ || (position.getFieldAttribute() == null && position
+ .getField() == FRACTION_FIELD)) {
+ position.setBeginIndex(index - len);
+ position.setEndIndex(index);
+ }
+ }
+ }
+ }
+
+ private void formatExponent(int exponent, StringBuffer buffer,
+ FieldPosition position, Vector fields) {
+ String output = Integer.toString(exponent);
+ int offset = 0;
+ int total = output.length();
+
+ buffer.append(symbols.getExponential());
+
+ int currentIndex = buffer.length();
+ handleField(Field.EXPONENT_SYMBOL, currentIndex - 1, currentIndex,
+ position, fields);
+
+ if (exponent < 0) {
+ buffer.append(getNegativePrefix());
+ offset = 1;
+ total--;
+ } else
+ buffer.append(getPositivePrefix());
+
+ int prefixLen = (exponent < 0) ? getNegativePrefix().length()
+ : getPositivePrefix().length();
+ if (prefixLen > 0) {
+ currentIndex = buffer.length();
+ handleField(Field.EXPONENT_SIGN, currentIndex - prefixLen,
+ currentIndex, position, fields);
+ }
+
+ if (minExponentDigits > total) {
+ for (int i = minExponentDigits - total; --i >= 0;)
+ buffer.append(zero);
+ }
+
+ for (int i = offset; i < output.length(); i++)
+ buffer.append((char) (zero + (output.charAt(i) - '0')));
+
+ handleField(Field.EXPONENT, currentIndex, buffer.length(), position,
+ fields);
+
+ if (exponent < 0)
+ buffer.append(getNegativeSuffix());
+ else
+ buffer.append(getPositiveSuffix());
+
+ int suffixLen = (exponent < 0) ? getNegativeSuffix().length()
+ : getPositiveSuffix().length();
+ if (suffixLen > 0) {
+ currentIndex = buffer.length();
+ handleField(Field.EXPONENT_SIGN, currentIndex - suffixLen,
+ currentIndex, position, fields);
}
- if (number instanceof BigInteger || number instanceof BigDecimal) {
- return dform.format(number, toAppendTo, pos);
+ }
+
+ /**
+ * Adds the field to the fields vector, or sets the <code>position</code>'s
+ * begin and end index if it has the same field attribute as
+ * <code>field</code>
+ *
+ * @param field
+ * @param begin
+ * @param end
+ * @param position
+ * @param fields
+ */
+ private void handleField(Field field, int begin, int end,
+ FieldPosition position, Vector fields) {
+ if (fields != null)
+ addToFields(fields, field, begin, end);
+ else {
+ if (position.getFieldAttribute() == field) {
+ position.setBeginIndex(begin);
+ position.setEndIndex(end);
+ }
+ }
+ }
+
+ private void addToFields(Vector fields, Field field, int begin, int end) {
+ FieldPosition pos = new FieldPosition(field);
+ pos.setBeginIndex(begin);
+ pos.setEndIndex(end);
+ fields.add(pos);
+ }
+
+ private void handleIntegerBegin(int index, FieldPosition position,
+ Vector fields, FieldPosition positionInteger) {
+ if (fields != null)
+ positionInteger.setBeginIndex(index);
+ else {
+ if (position.getFieldAttribute() == Field.INTEGER
+ || (position.getFieldAttribute() == null && position
+ .getField() == INTEGER_FIELD))
+ position.setBeginIndex(index);
+ }
+ }
+
+ private void handleIntegerEnd(int index, FieldPosition position,
+ Vector fields, FieldPosition positionInteger) {
+ if (fields != null) {
+ positionInteger.setEndIndex(index);
+ fields.add(positionInteger);
} else {
- return super.format(number, toAppendTo, pos);
+ if (position.getFieldAttribute() == Field.INTEGER
+ || (position.getFieldAttribute() == null && position
+ .getField() == INTEGER_FIELD))
+ position.setEndIndex(index);
}
}
@@ -267,6 +1099,12 @@
return (DecimalFormatSymbols) symbols.clone();
}
+ private char getDecimalSeparator() {
+ if (isCurrency())
+ return symbols.getMonetaryDecimalSeparator();
+ return symbols.getDecimalSeparator();
+ }
+
/**
* Answers the currency used by this decimal format.
*
@@ -274,7 +1112,7 @@
* @see DecimalFormatSymbols#getCurrency()
*/
public Currency getCurrency() {
- return Currency.getInstance(dform.getCurrency().getCurrencyCode());
+ return symbols.getCurrency();
}
/**
@@ -283,7 +1121,7 @@
* @return the number of digits grouped together
*/
public int getGroupingSize() {
- return dform.getGroupingSize();
+ return groupingSize;
}
/**
@@ -293,7 +1131,7 @@
* @return the multiplier
*/
public int getMultiplier() {
- return dform.getMultiplier();
+ return multiplier;
}
/**
@@ -302,7 +1140,7 @@
* @return the negative prefix
*/
public String getNegativePrefix() {
- return dform.getNegativePrefix();
+ return negPrefixPattern == null ? negativePrefix : negPrefixPattern;
}
/**
@@ -311,7 +1149,7 @@
* @return the negative suffix
*/
public String getNegativeSuffix() {
- return dform.getNegativeSuffix();
+ return negSuffixPattern == null ? negativeSuffix : negSuffixPattern;
}
/**
@@ -320,7 +1158,7 @@
* @return the positive prefix
*/
public String getPositivePrefix() {
- return dform.getPositivePrefix();
+ return posPrefixPattern == null ? positivePrefix : posPrefixPattern;
}
/**
@@ -329,7 +1167,7 @@
* @return the positive suffix
*/
public String getPositiveSuffix() {
- return dform.getPositiveSuffix();
+ return posSuffixPattern == null ? positiveSuffix : posSuffixPattern;
}
/**
@@ -341,7 +1179,17 @@
* @see #equals
*/
public int hashCode() {
- return dform.hashCode();
+ return super.hashCode() + symbols.hashCode() + groupingSize
+ + multiplier + positivePrefix.hashCode()
+ + positiveSuffix.hashCode() + negativePrefix.hashCode()
+ + negativeSuffix.hashCode()
+ + (decimalSeparatorAlwaysShown ? 1231 : 1237)
+ + (isCurrency() ? 1231 : 1237);
+ }
+
+ private boolean isCurrency() {
+ return posPrefixMonetary || posSuffixMonetary || negPrefixMonetary
+ || negSuffixMonetary;
}
/**
@@ -352,30 +1200,75 @@
* otherwise
*/
public boolean isDecimalSeparatorAlwaysShown() {
- return dform.isDecimalSeparatorAlwaysShown();
+ return decimalSeparatorAlwaysShown;
}
- /**
- * This value indicates whether the return object of the parse operation
- * will be of type BigDecimal. This value will default to false.
- *
- * @return true and parse will always return BigDecimals, false and the type
- * of the result will be Long or Double.
- */
- public boolean isParseBigDecimal() {
- return this.parseBigDecimal;
- }
-
- public void setParseIntegerOnly(boolean value) {
- dform.setParseIntegerOnly(value);
- }
-
- public boolean isParseIntegerOnly() {
- return dform.isParseIntegerOnly();
+ private int parseExponent(String string, ParsePosition position) {
+ int sign = 0;
+ int offset = position.getIndex();
+ position.setIndex(-1);
+ if (positivePrefix.length() != 0
+ && string.startsWith(positivePrefix, offset)) {
+ sign = 1;
+ offset += positivePrefix.length();
+ } else {
+ if (negativePrefix.length() != 0
+ && string.startsWith(negativePrefix, offset)) {
+ sign = -1;
+ offset += negativePrefix.length();
+ } else if (positivePrefix.length() != 0
+ && negativePrefix.length() != 0)
+ return 0;
+ }
+
+ boolean overflow = false;
+ int number = 0, lastOffset = offset;
+ int length = string.length();
+ while (offset < length) {
+ char ch = string.charAt(offset);
+ int value = getDigit(ch);
+ if (value == -1)
+ break;
+ int next = number * 10 - value;
+ if (next > number)
+ overflow = true;
+ number = next;
+ offset++;
+ }
+ if (offset == lastOffset)
+ return 0;
+
+ if (sign >= 0) {
+ if (positiveSuffix.length() == 0) {
+ position.setIndex(offset);
+ sign = 1;
+ } else if (string.startsWith(positiveSuffix, offset)) {
+ position.setIndex(offset + positiveSuffix.length());
+ sign = 1;
+ } else if (sign == 1)
+ return 0;
+ }
+ if (sign <= 0) {
+ if (negativeSuffix.length() == 0) {
+ position.setIndex(offset);
+ sign = -1;
+ } else if (string.startsWith(negativeSuffix, offset)) {
+ position.setIndex(offset + negativeSuffix.length());
+ sign = -1;
+ } else
+ return 0;
+ }
+ if (sign != -1) {
+ number = -number;
+ // catch MIN_VALUE case
+ if (number < 0)
+ overflow = true;
+ }
+ if (overflow)
+ return 1024; // Return any overflow number
+ return number;
}
- private static final Double NEGATIVE_ZERO_DOUBLE = new Double(-0.0);
-
/**
* Parse a Long or Double from the specified String starting at the index
* specified by the ParsePosition. If the string is successfully parsed, the
@@ -393,39 +1286,261 @@
* integer in the range of a long, otherwise the result is a Double.
*/
public Number parse(String string, ParsePosition position) {
- Number number = dform.parse(string, position);
- if (null == number) {
- return null;
+ int offset = position.getIndex();
+ if (offset < 0)
+ return error(position, offset);
+ if (string.startsWith(symbols.getNaN(), offset)) {
+ position.setIndex(offset + symbols.getNaN().length());
+ return new Double(Double.NaN);
+ }
+
+ int sign = 0;
+ boolean posPre = positivePrefix.length() > 0
+ && string.startsWith(positivePrefix, offset);
+ if (positivePrefix.equals(negativePrefix)) {
+ if (positivePrefix.length() > 0 && !posPre)
+ return error(position, offset);
+ offset += positivePrefix.length();
+ } else {
+ boolean negPre = negativePrefix.length() > 0
+ && string.startsWith(negativePrefix, offset);
+ if ((posPre || positivePrefix.length() == 0
+ && negativePrefix.length() > 0)
+ && !negPre) {
+ sign = 1;
+ offset += positivePrefix.length();
+ } else if ((negPre || negativePrefix.length() == 0
+ && positivePrefix.length() > 0)
+ && !posPre) {
+ sign = -1;
+ offset += negativePrefix.length();
+ } else if (positivePrefix.length() != 0
+ && negativePrefix.length() != 0)
+ return error(position, offset);
}
- if (this.isParseBigDecimal()) {
- if (number instanceof Long) {
- return new BigDecimal(number.longValue());
- }
- if ((number instanceof Double) && !((Double) number).isInfinite()
- && !((Double) number).isNaN()) {
- return new BigDecimal(number.doubleValue());
+ double dnumber = 0;
+ long max = Long.MIN_VALUE / 10;
+ boolean overflow = false, useFloat = false;
+ long number = 0, fraction = 0;
+ int length = string.length(), lastValid = -1, decimalDigits = 0, fractionDigits = 0, exponent = 0;
+ if (string.startsWith(symbols.getInfinity(), offset)) {
+ lastValid = (offset += symbols.getInfinity().length());
+ dnumber = Double.POSITIVE_INFINITY;
+ } else {
+ boolean digits = false;
+ while (offset < length) {
+ char ch = string.charAt(offset);
+ if (ch == getDecimalSeparator()) {
+ if (!isParseIntegerOnly()) {
+ offset++;
+ lastValid = offset;
+ StringBuffer fractDigits = new StringBuffer();
+ while (offset < length) {
+ ch = string.charAt(offset);
+ if (getDigit(ch) == -1)
+ break;
+ fractDigits.append(ch);
+ offset++;
+ lastValid = offset;
+ }
+ int len = fractDigits.length() - 1;
+ while (len >= 0
+ && getDigit(fractDigits.charAt(len)) == 0) {
+ digits = true;
+ len--;
+ }
+ for (int i = 0; i <= len; i++) {
+ digits = true;
+ int value = getDigit(fractDigits.charAt(i));
+ if (!overflow) {
+ if (max > fraction) {
+ overflow = true;
+ break;
+ }
+ long next = fraction * 10 - value;
+ if (next <= fraction) {
+ fraction = next;
+ fractionDigits++;
+ } else {
+ overflow = true;
+ break;
+ }
+ }
+ }
+ if (ch == symbols.getExponential()) {
+ ParsePosition pos = new ParsePosition(offset + 1);
+ exponent = parseExponent(string, pos);
+ if (pos.getIndex() != -1)
+ lastValid = pos.getIndex();
+ }
+ }
+ break;
+ }
+ int value = getDigit(ch);
+ if (value != -1) {
+ digits = true;
+ if (number != 0 || value > 0) {
+ decimalDigits++;
+ if (useFloat)
+ dnumber = dnumber * 10 - value;
+ else {
+ if (max <= number) {
+ long next = number * 10 - value;
+ if (next > number) { // Overflow
+ dnumber = number * 10.0 - value;
+ useFloat = true;
+ } else
+ number = next;
+ } else { // Overflow
+ dnumber = number * 10.0 - value;
+ useFloat = true;
+ }
+ }
+ }
+ lastValid = offset + 1;
+ } else if (ch == symbols.getExponential()) {
+ ParsePosition pos = new ParsePosition(offset + 1);
+ exponent = parseExponent(string, pos);
+ if (pos.getIndex() != -1)
+ lastValid = pos.getIndex();
+ break;
+ } else if (ch != symbols.getGroupingSeparator()
+ || !isGroupingUsed())
+ break;
+ offset++;
}
- if (number instanceof BigInteger) {
- return new BigDecimal(number.doubleValue());
+ if (!digits)
+ return error(position, position.getIndex());
+ }
+
+ if (sign == 0) {
+ boolean posSuf = positiveSuffix.length() > 0
+ && string.startsWith(positiveSuffix, offset);
+ boolean negSuf = negativeSuffix.length() > 0
+ && string.startsWith(negativeSuffix, offset);
+ if (posSuf != negSuf) {
+ if (posSuf)
+ sign = 1;
+ else
+ sign = -1;
+ } else if (positiveSuffix.equals(negativeSuffix))
+ return error(position, lastValid);
+ }
+ if (sign >= 0) {
+ if (positiveSuffix.length() == 0) {
+ position.setIndex(lastValid);
+ sign = 1;
+ } else if (offset == lastValid
+ && string.startsWith(positiveSuffix, offset)) {
+ position.setIndex(offset + positiveSuffix.length());
+ sign = 1;
+ } else if (sign == 1)
+ return error(position, lastValid);
+ }
+ if (sign <= 0) {
+ if (negativeSuffix.length() == 0) {
+ position.setIndex(lastValid);
+ sign = -1;
+ } else if (offset == lastValid
+ && string.startsWith(negativeSuffix, offset)) {
+ position.setIndex(offset + negativeSuffix.length());
+ sign = -1;
+ } else
+ return error(position, lastValid);
+ }
+
+ if (!useFloat
+ && ((fraction != 0 && exponent == 0) || exponent < 0
+ || exponent + decimalDigits - 1 > 19
+ || exponent < fractionDigits || overflow)) {
+ dnumber = number;
+ useFloat = true;
+ }
+ if (!useFloat && number != 0) {
+ long next = number;
+ for (int i = exponent; --i >= 0;) {
+ if (max > next) { // Overflow
+ dnumber = number;
+ useFloat = true;
+ break;
+ }
+ next *= 10;
}
- if (number instanceof com.ibm.icu.math.BigDecimal) {
- return new BigDecimal(number.toString());
+ number = next;
+ }
+ if (fraction != 0 && !useFloat) {
+ long next = fraction;
+ for (int i = exponent - fractionDigits; --i >= 0;)
+ next *= 10;
+ long result = number + next;
+ if (next < number)
+ number = result;
+ else { // Overflow
+ dnumber = number;
+ exponent = 0;
+ fraction = next;
+ fractionDigits = 0;
+ useFloat = true;
}
- return number;
- } else {
- if ((number instanceof com.ibm.icu.math.BigDecimal)
- || (number instanceof BigInteger)) {
- return new Double(number.doubleValue());
+ }
+ if (useFloat) {
+ if (fraction != 0)
+ dnumber += fraction / Math.pow(10.0, fractionDigits);
+ if (exponent != 0)
+ dnumber *= Math.pow(10.0, exponent);
+ }
+ if (!useFloat && number == 0 && sign == -1 && !isParseIntegerOnly()) {
+ dnumber = -1.0 * 0;
+ useFloat = true;
+ }
+
+ if (multiplier != 1) {
+ if (dnumber != 0) {
+ dnumber /= multiplier;
+ } else {
+ long lResult = number / multiplier;
+ double dResult = (double) number / multiplier;
+ if (dResult == lResult)
+ number = lResult;
+ else {
+ dnumber = dResult;
+ useFloat = true;
+ }
}
+ }
+
+ if (number == Long.MIN_VALUE && sign == 1) {
+ dnumber = number;
+ useFloat = true;
+ }
- if (this.isParseIntegerOnly() && number.equals(NEGATIVE_ZERO_DOUBLE)) {
- return new Long(0);
- }
- return number;
+ if (useFloat)
+ return new Double(sign < 0 ? dnumber : -dnumber);
+ return new Long(sign < 0 ? number : -number);
+ }
+ private String quote(String string, String special) {
+ for (int i = 0; i < special.length(); i++) {
+ char ch = special.charAt(i);
+ if (string.indexOf(ch) != -1
+ && (i < 5 || ch != patternChars.charAt(i)))
+ return '\'' + string + '\'';
}
+ return string;
+ }
+ private int scale(double value) {
+ if (value == 0.0)
+ return 0;
+ int scale = (int) Math.floor(Math.log(value) / log10);
+ return Math.pow(10.0, scale) > value ? scale - 1 : scale;
+ }
+
+ private String expandAffix(String affix) {
+ String newAffix = convertPattern(affix, patternChars, new String(
+ symbols.patternChars), false);
+ return convertCurrencySymbols(newAffix);
}
/**
@@ -435,9 +1550,19 @@
* the DecimalFormatSymbols
*/
public void setDecimalFormatSymbols(DecimalFormatSymbols value) {
- symbols = (DecimalFormatSymbols) value.clone();
- icuSymbols = adapt2ICU(symbols);
- dform.setDecimalFormatSymbols(icuSymbols);
+ if (value != null) {
+ symbols = (DecimalFormatSymbols) value.clone();
+ zero = symbols.getZeroDigit();
+ // Update localized affix
+ if (posPrefixPattern != null)
+ posPrefixPattern = expandAffix(positivePrefix);
+ if (posSuffixPattern != null)
+ posSuffixPattern = expandAffix(positiveSuffix);
+ if (negPrefixPattern != null)
+ negPrefixPattern = expandAffix(negativePrefix);
+ if (negSuffixPattern != null)
+ negSuffixPattern = expandAffix(negativeSuffix);
+ }
}
/**
@@ -448,8 +1573,6 @@
* @see DecimalFormatSymbols#setCurrency(Currency)
*/
public void setCurrency(Currency currency) {
- dform.setCurrency(com.ibm.icu.util.Currency.getInstance(currency
- .getCurrencyCode()));
symbols.setCurrency(currency);
}
@@ -462,7 +1585,7 @@
* false otherwise
*/
public void setDecimalSeparatorAlwaysShown(boolean value) {
- dform.setDecimalSeparatorAlwaysShown(value);
+ decimalSeparatorAlwaysShown = value;
}
/**
@@ -472,7 +1595,7 @@
* the number of digits grouped together
*/
public void setGroupingSize(int value) {
- dform.setGroupingSize(value);
+ groupingSize = (byte) value;
}
/**
@@ -485,8 +1608,9 @@
* the maximum number of fraction digits
*/
public void setMaximumFractionDigits(int value) {
- super.setMaximumFractionDigits(value);
- dform.setMaximumFractionDigits(value);
+ super
+ .setMaximumFractionDigits(value > DOUBLE_FRACTION_DIGITS ? DOUBLE_FRACTION_DIGITS
+ : value);
}
/**
@@ -499,8 +1623,9 @@
* the maximum number of integer digits
*/
public void setMaximumIntegerDigits(int value) {
- super.setMaximumIntegerDigits(value);
- dform.setMaximumIntegerDigits(value);
+ super
+ .setMaximumIntegerDigits(value > DOUBLE_INTEGER_DIGITS ? DOUBLE_INTEGER_DIGITS
+ : value);
}
/**
@@ -511,8 +1636,9 @@
* the minimum number of fraction digits
*/
public void setMinimumFractionDigits(int value) {
- super.setMinimumFractionDigits(value);
- dform.setMinimumFractionDigits(value);
+ super
+ .setMinimumFractionDigits(value > DOUBLE_FRACTION_DIGITS ? DOUBLE_FRACTION_DIGITS
+ : value);
}
/**
@@ -523,8 +1649,9 @@
* the minimum number of integer digits
*/
public void setMinimumIntegerDigits(int value) {
- super.setMinimumIntegerDigits(value);
- dform.setMinimumIntegerDigits(value);
+ super
+ .setMinimumIntegerDigits(value > DOUBLE_INTEGER_DIGITS ? DOUBLE_INTEGER_DIGITS
+ : value);
}
/**
@@ -535,7 +1662,7 @@
* the multiplier
*/
public void setMultiplier(int value) {
- dform.setMultiplier(value);
+ multiplier = value;
}
/**
@@ -545,7 +1672,9 @@
* the negative prefix
*/
public void setNegativePrefix(String value) {
- dform.setNegativePrefix(value);
+ negativePrefix = value;
+ negPrefixMonetary = false;
+ negPrefixPattern = null;
}
/**
@@ -555,7 +1684,9 @@
* the negative suffix
*/
public void setNegativeSuffix(String value) {
- dform.setNegativeSuffix(value);
+ negativeSuffix = value;
+ negSuffixMonetary = false;
+ negSuffixPattern = null;
}
/**
@@ -565,7 +1696,9 @@
* the positive prefix
*/
public void setPositivePrefix(String value) {
- dform.setPositivePrefix(value);
+ positivePrefix = value;
+ posPrefixMonetary = false;
+ posPrefixPattern = null;
}
/**
@@ -575,15 +1708,9 @@
* the positive suffix
*/
public void setPositiveSuffix(String value) {
- dform.setPositiveSuffix(value);
- }
-
- /**
- * Let users change the behavior of a DecimalFormat, If set to true all the
- * returned objects will be of type BigDecimal
- */
- public void setParseBigDecimal(boolean newValue) {
- this.parseBigDecimal = newValue;
+ positiveSuffix = value;
+ posSuffixMonetary = false;
+ posSuffixPattern = null;
}
/**
@@ -593,7 +1720,7 @@
* @return the localized pattern
*/
public String toLocalizedPattern() {
- return dform.toLocalizedPattern();
+ return toPatternString(symbols.getLocalPatternChars());
}
/**
@@ -603,18 +1730,105 @@
* @return the non-localized pattern
*/
public String toPattern() {
- return dform.toPattern();
+ return toPatternString(patternChars);
}
-
- private void writeObject(ObjectOutputStream stream) throws IOException,
- ClassNotFoundException {
- throw new NotYetImplementedException();
+ private String toPatternString(String localPatternChars) {
+ StringBuffer pattern = new StringBuffer();
+ boolean groupingUsed = isGroupingUsed() && getGroupingSize() > 0;
+ if (!groupingUsed || groupingSize > getMinimumIntegerDigits()) {
+ if (groupingUsed) {
+ if (useExponentialNotation) {
+ for (int i = 0; i < getMaximumIntegerDigits()
+ - groupingSize - 1; i++)
+ pattern.append('#');
+ }
+ pattern.append("#,");
+ for (int i = 0; i < groupingSize - getMinimumIntegerDigits(); i++)
+ pattern.append('#');
+ } else if (useExponentialNotation) {
+ for (int i = 0; i < getMaximumIntegerDigits()
+ - getMinimumIntegerDigits(); i++)
+ pattern.append('#');
+ } else
+ pattern.append('#');
+ for (int i = 0; i < getMinimumIntegerDigits(); i++)
+ pattern.append('0');
+ } else {
+ if (useExponentialNotation) {
+ for (int i = 0; i < getMaximumIntegerDigits()
+ - getMinimumIntegerDigits(); i++)
+ pattern.append('#');
+ } else
+ pattern.append('#');
+ for (int i = 0; i < getMinimumIntegerDigits() - groupingSize; i++)
+ pattern.append('0');
+ pattern.append(',');
+ for (int i = 0; i < groupingSize; i++)
+ pattern.append('0');
+ }
+ if (getMaximumFractionDigits() > 0 || isDecimalSeparatorAlwaysShown()) {
+ pattern.append('.');
+ for (int i = 0; i < getMinimumFractionDigits(); i++)
+ pattern.append('0');
+ for (int i = 0; i < getMaximumFractionDigits()
+ - getMinimumFractionDigits(); i++)
+ pattern.append('#');
+ }
+ if (useExponentialNotation) {
+ pattern.append('E');
+ for (int i = 0; i < minExponentDigits; i++)
+ pattern.append('0');
+ }
+
+ String localPattern = pattern.toString();
+ String result = quote(positivePrefix, localPatternChars) + localPattern
+ + quote(positiveSuffix, localPatternChars);
+ if (!negativePrefix.equals(symbols.getMinusSign() + positivePrefix)
+ || !negativeSuffix.equals(positiveSuffix)) {
+ result = result + ';' + quote(negativePrefix, localPatternChars)
+ + localPattern + quote(negativeSuffix, localPatternChars);
+ }
+ if (localPatternChars != patternChars)
+ result = convertPattern(result, patternChars, localPatternChars,
+ false);
+ return result;
}
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
- throw new NotYetImplementedException();
+ stream.defaultReadObject();
+ if (serialVersionOnStream == 0)
+ useExponentialNotation = false;
+ zero = symbols.getZeroDigit();
+ serialVersionOnStream = 2;
+ if (posPrefixPattern != null)
+ posPrefixMonetary = positivePrefix.indexOf(CURRENCY_SYMBOL) > -1;
+ if (posSuffixPattern != null)
+ posSuffixMonetary = positiveSuffix.indexOf(CURRENCY_SYMBOL) > -1;
+ if (negPrefixPattern != null)
+ negPrefixMonetary = negativePrefix.indexOf(CURRENCY_SYMBOL) > -1;
+ if (negSuffixPattern != null)
+ negSuffixMonetary = negativeSuffix.indexOf(CURRENCY_SYMBOL) > -1;
+ if (getMinimumIntegerDigits() > DOUBLE_INTEGER_DIGITS
+ || getMaximumIntegerDigits() > DOUBLE_INTEGER_DIGITS
+ || getMinimumFractionDigits() > DOUBLE_FRACTION_DIGITS
+ || getMaximumFractionDigits() > DOUBLE_FRACTION_DIGITS)
+ throw new InvalidObjectException(org.apache.harmony.luni.util.Msg
+ .getString("K00f9"));
+ }
+
+ long intPow(int exp) {
+ long result = 1;
+ for (int i = 0; i < exp; i++)
+ result *= 10;
+ return result;
+ }
+
+ int getDigit(char ch) {
+ int diff = ch - zero;
+ if (diff >= 0 && diff <= 9)
+ return diff;
+ return Character.digit(ch, 10);
}
-
}
Modified: incubator/harmony/enhanced/classlib/trunk/modules/text/src/test/java/org/apache/harmony/tests/java/text/AllTests.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/text/src/test/java/org/apache/harmony/tests/java/text/AllTests.java?rev=393171&r1=393170&r2=393171&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/text/src/test/java/org/apache/harmony/tests/java/text/AllTests.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/text/src/test/java/org/apache/harmony/tests/java/text/AllTests.java Tue Apr 11 03:02:16 2006
@@ -36,7 +36,6 @@
suite.addTestSuite(MessageFormatTest.class);
suite.addTestSuite(ChoiceFormatTest.class);
suite.addTestSuite(DataFormatFieldTest.class);
- suite.addTestSuite(DecimalFormatTest.class);
//$JUnit-END$
return suite;
}