2004-05-05 Guilhem Lavaux <guilhem@kaffe.org>

* java/text/DecimalFormat.java
	(MAXIMUM_INTEGER_DIGITS): New constant to keep the numeric value 309.
	(applyPatternWithSymbols): Use MAXIMUM_INTEGER_DIGITS.
	(parse): Fixed handling of exponentiation notation and grouping.

2004-05-05  Guilhem Lavaux <guilhem@kaffe.org>

	* java/text/DecimalFormat.java
	(scanFix): Build attribute array. Fixed error reporting.
	(applyPatternWithSymbols): Store attributes for the prefix and
	suffix.
	(formatInternal): New method. Changed the way the string is
	computed. Implemented attributes. Cleant up rounding in
	exponential notation.
	(format): Use formatInternal.
	(formatToCharacterIterator): New method.
	(exponentRound, negativePrefixRanges, positivePrefixRanges,
	negativePrefixAttrs, positivePrefixAttrs, negativeSuffixRanges,
	positiveSuffixRanges, negativeSuffixAttrs, positiveSuffixAttrs):
	New fields.

From-SVN: r81491
This commit is contained in:
Guilhem Lavaux 2004-05-04 22:00:30 +00:00 committed by Michael Koch
parent aff9d141f6
commit 8cf1edb30c
2 changed files with 184 additions and 64 deletions

View File

@ -1,3 +1,26 @@
2004-05-05 Guilhem Lavaux <guilhem@kaffe.org>
* java/text/DecimalFormat.java
(MAXIMUM_INTEGER_DIGITS): New constant to keep the numeric value 309.
(applyPatternWithSymbols): Use MAXIMUM_INTEGER_DIGITS.
(parse): Fixed handling of exponentiation notation and grouping.
2004-05-05 Guilhem Lavaux <guilhem@kaffe.org>
* java/text/DecimalFormat.java
(scanFix): Build attribute array. Fixed error reporting.
(applyPatternWithSymbols): Store attributes for the prefix and
suffix.
(formatInternal): New method. Changed the way the string is
computed. Implemented attributes. Cleant up rounding in
exponential notation.
(format): Use formatInternal.
(formatToCharacterIterator): New method.
(exponentRound, negativePrefixRanges, positivePrefixRanges,
negativePrefixAttrs, positivePrefixAttrs, negativeSuffixRanges,
positiveSuffixRanges, negativeSuffixAttrs, positiveSuffixAttrs):
New fields.
2004-05-04 Dalibor Topic <robilad@kaffe.org> 2004-05-04 Dalibor Topic <robilad@kaffe.org>
* java/security/interfaces/DSAKeyPairGenerator.java, * java/security/interfaces/DSAKeyPairGenerator.java,

View File

@ -37,7 +37,13 @@ exception statement from your version. */
package java.text; package java.text;
import gnu.java.text.AttributedFormatBuffer;
import gnu.java.text.FormatBuffer;
import gnu.java.text.FormatCharacterIterator;
import gnu.java.text.StringFormatBuffer;
import java.util.Currency; import java.util.Currency;
import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@ -58,37 +64,48 @@ public class DecimalFormat extends NumberFormat
{ {
// This is a helper for applyPatternWithSymbols. It reads a prefix // This is a helper for applyPatternWithSymbols. It reads a prefix
// or a suffix. It can cause some side-effects. // or a suffix. It can cause some side-effects.
private final int scanFix (String pattern, int index, StringBuffer buf, private final int scanFix (String pattern, int index, FormatBuffer buf,
String patChars, DecimalFormatSymbols syms, String patChars, DecimalFormatSymbols syms,
boolean is_suffix) boolean is_suffix)
{ {
int len = pattern.length(); int len = pattern.length();
buf.setLength(0); boolean quoteStarted = false;
buf.clear();
boolean multiplierSet = false; boolean multiplierSet = false;
while (index < len) while (index < len)
{ {
char c = pattern.charAt(index); char c = pattern.charAt(index);
if (quoteStarted)
{
if (c == '\'')
quoteStarted = false;
else
buf.append(c);
index++;
continue;
}
if (c == '\'' && index + 1 < len if (c == '\'' && index + 1 < len
&& pattern.charAt(index + 1) == '\'') && pattern.charAt(index + 1) == '\'')
{ {
buf.append(c); buf.append(c);
++index; index++;
} }
else if (c == '\'' && index + 2 < len else if (c == '\'')
&& pattern.charAt(index + 2) == '\'')
{ {
buf.append(pattern.charAt(index + 1)); quoteStarted = true;
index += 2;
} }
else if (c == '\u00a4') else if (c == '\u00a4')
{ {
if (index + 1 < len && pattern.charAt(index + 1) == '\u00a4') if (index + 1 < len && pattern.charAt(index + 1) == '\u00a4')
{ {
buf.append(syms.getInternationalCurrencySymbol()); buf.append(syms.getInternationalCurrencySymbol(), NumberFormat.Field.CURRENCY);
++index; index++;
} }
else else
buf.append(syms.getCurrencySymbol()); buf.append(syms.getCurrencySymbol(), NumberFormat.Field.CURRENCY);
} }
else if (c == syms.getPercent()) else if (c == syms.getPercent())
{ {
@ -97,7 +114,7 @@ public class DecimalFormat extends NumberFormat
"- index: " + index); "- index: " + index);
multiplierSet = true; multiplierSet = true;
multiplier = 100; multiplier = 100;
buf.append(c); buf.append(c, NumberFormat.Field.PERCENT);
} }
else if (c == syms.getPerMill()) else if (c == syms.getPerMill())
{ {
@ -106,7 +123,7 @@ public class DecimalFormat extends NumberFormat
"- index: " + index); "- index: " + index);
multiplierSet = true; multiplierSet = true;
multiplier = 1000; multiplier = 1000;
buf.append(c); buf.append(c, NumberFormat.Field.PERMILLE);
} }
else if (patChars.indexOf(c) != -1) else if (patChars.indexOf(c) != -1)
{ {
@ -115,9 +132,12 @@ public class DecimalFormat extends NumberFormat
} }
else else
buf.append(c); buf.append(c);
++index; index++;
} }
if (quoteStarted)
throw new IllegalArgumentException ("pattern is lacking a closing quote");
return index; return index;
} }
@ -259,6 +279,16 @@ public class DecimalFormat extends NumberFormat
useExponentialNotation = true; useExponentialNotation = true;
minExponentDigits = (byte) zeroCount; minExponentDigits = (byte) zeroCount;
} }
maximumIntegerDigits = groupingSize;
groupingSize = 0;
if (maximumIntegerDigits > minimumIntegerDigits && maximumIntegerDigits > 0)
{
minimumIntegerDigits = 1;
exponentRound = maximumIntegerDigits;
}
else
exponentRound = 1;
} }
return index; return index;
@ -304,17 +334,23 @@ public class DecimalFormat extends NumberFormat
minimumFractionDigits = 0; minimumFractionDigits = 0;
minimumIntegerDigits = 1; minimumIntegerDigits = 1;
StringBuffer buf = new StringBuffer (); AttributedFormatBuffer buf = new AttributedFormatBuffer ();
String patChars = patternChars (syms); String patChars = patternChars (syms);
int max = pattern.length(); int max = pattern.length();
int index = scanFix (pattern, 0, buf, patChars, syms, false); int index = scanFix (pattern, 0, buf, patChars, syms, false);
positivePrefix = buf.toString(); buf.sync();
positivePrefix = buf.getBuffer().toString();
positivePrefixRanges = buf.getRanges();
positivePrefixAttrs = buf.getAttributes();
index = scanFormat (pattern, index, patChars, syms, true); index = scanFormat (pattern, index, patChars, syms, true);
index = scanFix (pattern, index, buf, patChars, syms, true); index = scanFix (pattern, index, buf, patChars, syms, true);
positiveSuffix = buf.toString(); buf.sync();
positiveSuffix = buf.getBuffer().toString();
positiveSuffixRanges = buf.getRanges();
positiveSuffixAttrs = buf.getAttributes();
if (index == pattern.length()) if (index == pattern.length())
{ {
@ -329,14 +365,20 @@ public class DecimalFormat extends NumberFormat
"expected - index: " + index); "expected - index: " + index);
index = scanFix (pattern, index + 1, buf, patChars, syms, false); index = scanFix (pattern, index + 1, buf, patChars, syms, false);
negativePrefix = buf.toString(); buf.sync();
negativePrefix = buf.getBuffer().toString();
negativePrefixRanges = buf.getRanges();
negativePrefixAttrs = buf.getAttributes();
// We parse the negative format for errors but we don't let // We parse the negative format for errors but we don't let
// it side-effect this object. // it side-effect this object.
index = scanFormat (pattern, index, patChars, syms, false); index = scanFormat (pattern, index, patChars, syms, false);
index = scanFix (pattern, index, buf, patChars, syms, true); index = scanFix (pattern, index, buf, patChars, syms, true);
negativeSuffix = buf.toString(); buf.sync();
negativeSuffix = buf.getBuffer().toString();
negativeSuffixRanges = buf.getRanges();
negativeSuffixAttrs = buf.getAttributes();
if (index != pattern.length()) if (index != pattern.length())
throw new IllegalArgumentException ("end of pattern expected " + throw new IllegalArgumentException ("end of pattern expected " +
@ -409,39 +451,43 @@ public class DecimalFormat extends NumberFormat
&& useExponentialNotation == dup.useExponentialNotation); && useExponentialNotation == dup.useExponentialNotation);
} }
public StringBuffer format (double number, StringBuffer dest, protected void formatInternal (double number, FormatBuffer dest,
FieldPosition fieldPos) FieldPosition fieldPos)
{ {
// A very special case. // A very special case.
if (Double.isNaN(number)) if (Double.isNaN(number))
{ {
dest.append(symbols.getNaN()); dest.append(symbols.getNaN());
if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD) if (fieldPos != null &&
(fieldPos.getField() == INTEGER_FIELD ||
fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
{ {
int index = dest.length(); int index = dest.length();
fieldPos.setBeginIndex(index - symbols.getNaN().length()); fieldPos.setBeginIndex(index - symbols.getNaN().length());
fieldPos.setEndIndex(index); fieldPos.setEndIndex(index);
} }
return dest; return;
} }
boolean is_neg = number < 0; boolean is_neg = number < 0;
if (is_neg) if (is_neg)
{ {
if (negativePrefix != null) if (negativePrefix != null)
dest.append(negativePrefix); dest.append(negativePrefix, negativePrefixRanges, negativePrefixAttrs);
else else
{ {
dest.append(symbols.getMinusSign()); dest.append(symbols.getMinusSign(), NumberFormat.Field.SIGN);
dest.append(positivePrefix); dest.append(positivePrefix, positivePrefixRanges, positivePrefixAttrs);
} }
number = - number; number = - number;
} }
else else
dest.append(positivePrefix); dest.append(positivePrefix, positivePrefixRanges, positivePrefixAttrs);
int integerBeginIndex = dest.length(); int integerBeginIndex = dest.length();
int integerEndIndex = 0; int integerEndIndex = 0;
int zeroStart = symbols.getZeroDigit() - '0';
if (Double.isInfinite (number)) if (Double.isInfinite (number))
{ {
dest.append(symbols.getInfinity()); dest.append(symbols.getInfinity());
@ -457,6 +503,7 @@ public class DecimalFormat extends NumberFormat
if (useExponentialNotation) if (useExponentialNotation)
{ {
exponent = (long) Math.floor (Math.log(number) / Math.log(10)); exponent = (long) Math.floor (Math.log(number) / Math.log(10));
exponent = exponent - (exponent % exponentRound);
if (minimumIntegerDigits > 0) if (minimumIntegerDigits > 0)
exponent -= minimumIntegerDigits - 1; exponent -= minimumIntegerDigits - 1;
baseNumber = (number / Math.pow(10.0, exponent)); baseNumber = (number / Math.pow(10.0, exponent));
@ -468,22 +515,32 @@ public class DecimalFormat extends NumberFormat
baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1); baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);
int index = dest.length(); int index = dest.length();
double intPart = Math.floor(baseNumber); //double intPart = Math.floor(baseNumber);
int count = 0; String intPart = Long.toString((long)Math.floor(baseNumber));
while (count < maximumIntegerDigits int count, groupPosition = intPart.length();
&& (intPart > 0 || count < minimumIntegerDigits))
dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
for (count = 0; count < minimumIntegerDigits-intPart.length(); count++)
dest.append(symbols.getZeroDigit());
for (count = 0;
count < maximumIntegerDigits && count < intPart.length();
count++)
{ {
long dig = (long) (intPart % 10); int dig = intPart.charAt(count);
intPart = Math.floor(intPart / 10);
// Append group separator if required. // Append group separator if required.
if (groupingUsed && count > 0 && groupingSize != 0 && count % groupingSize == 0) if (groupingUsed && count > 0 && groupingSize != 0 && groupPosition % groupingSize == 0)
dest.insert(index, symbols.getGroupingSeparator()); {
dest.append(symbols.getGroupingSeparator(), NumberFormat.Field.GROUPING_SEPARATOR);
dest.insert(index, (char) (symbols.getZeroDigit() + dig)); dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
++count;
} }
dest.append((char) (zeroStart + dig));
groupPosition--;
}
dest.setDefaultAttribute(null);
integerEndIndex = dest.length(); integerEndIndex = dest.length();
@ -491,10 +548,24 @@ public class DecimalFormat extends NumberFormat
int consecutive_zeros = 0; int consecutive_zeros = 0;
int total_digits = 0; int total_digits = 0;
int localMaximumFractionDigits = maximumFractionDigits;
if (useExponentialNotation)
localMaximumFractionDigits += minimumIntegerDigits - count;
// Strip integer part from NUMBER. // Strip integer part from NUMBER.
double fracPart = baseNumber - Math.floor(baseNumber); double fracPart = baseNumber - Math.floor(baseNumber);
if ( ((fracPart != 0 || minimumFractionDigits > 0) && localMaximumFractionDigits > 0)
|| decimalSeparatorAlwaysShown)
{
dest.append (symbols.getDecimalSeparator(), NumberFormat.Field.DECIMAL_SEPARATOR);
}
dest.setDefaultAttribute(NumberFormat.Field.FRACTION);
for (count = 0; for (count = 0;
count < maximumFractionDigits count < localMaximumFractionDigits
&& (fracPart != 0 || count < minimumFractionDigits); && (fracPart != 0 || count < minimumFractionDigits);
++count) ++count)
{ {
@ -517,55 +588,76 @@ public class DecimalFormat extends NumberFormat
total_digits - minimumFractionDigits); total_digits - minimumFractionDigits);
if (extra_zeros > 0) if (extra_zeros > 0)
{ {
dest.setLength(dest.length() - extra_zeros); dest.cutTail(extra_zeros);
total_digits -= extra_zeros; total_digits -= extra_zeros;
} if (total_digits == 0 && !decimalSeparatorAlwaysShown)
dest.cutTail(1);
// If required, add the decimal symbol.
if (decimalSeparatorAlwaysShown
|| total_digits > 0)
{
dest.insert(decimal_index, symbols.getDecimalSeparator());
if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
{
fieldPos.setBeginIndex(decimal_index + 1);
fieldPos.setEndIndex(dest.length());
}
} }
// Finally, print the exponent. // Finally, print the exponent.
if (useExponentialNotation) if (useExponentialNotation)
{ {
dest.append(symbols.getExponential()); dest.append(symbols.getExponential(), NumberFormat.Field.EXPONENT_SYMBOL);
if (exponent < 0) if (exponent < 0)
{ {
dest.append (symbols.getMinusSign ()); dest.append (symbols.getMinusSign (), NumberFormat.Field.EXPONENT_SIGN);
exponent = - exponent; exponent = - exponent;
} }
index = dest.length(); index = dest.length();
dest.setDefaultAttribute(NumberFormat.Field.EXPONENT);
String exponentString = Long.toString ((long) exponent);
for (count = 0; count < minExponentDigits-exponentString.length();
count++)
dest.append((char) symbols.getZeroDigit());
for (count = 0; for (count = 0;
exponent > 0 || count < minExponentDigits; count < exponentString.length();
++count) ++count)
{ {
long dig = exponent % 10; int dig = exponentString.charAt(count);
exponent /= 10; dest.append((char) (zeroStart + dig));
dest.insert(index, (char) (symbols.getZeroDigit() + dig));
} }
} }
} }
if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD) if (fieldPos != null &&
(fieldPos.getField() == INTEGER_FIELD ||
fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
{ {
fieldPos.setBeginIndex(integerBeginIndex); fieldPos.setBeginIndex(integerBeginIndex);
fieldPos.setEndIndex(integerEndIndex); fieldPos.setEndIndex(integerEndIndex);
} }
dest.append((is_neg && negativeSuffix != null) if (is_neg && negativeSuffix != null)
? negativeSuffix dest.append(negativeSuffix, negativeSuffixRanges, negativeSuffixAttrs);
: positiveSuffix); else
dest.append(positiveSuffix, positiveSuffixRanges, positiveSuffixAttrs);
}
public StringBuffer format (double number, StringBuffer dest,
FieldPosition fieldPos)
{
formatInternal (number, new StringFormatBuffer(dest), fieldPos);
return dest; return dest;
} }
public AttributedCharacterIterator formatToCharacterIterator (Object value)
{
AttributedFormatBuffer sbuf = new AttributedFormatBuffer();
if (value instanceof Number)
formatInternal(((Number) value).doubleValue(), sbuf, null);
else
throw new IllegalArgumentException
("Cannot format given Object as a Number");
sbuf.sync();
return new FormatCharacterIterator(sbuf.getBuffer().toString(),
sbuf.getRanges(),
sbuf.getAttributes());
}
public StringBuffer format (long number, StringBuffer dest, public StringBuffer format (long number, StringBuffer dest,
FieldPosition fieldPos) FieldPosition fieldPos)
{ {
@ -964,7 +1056,7 @@ public class DecimalFormat extends NumberFormat
// digits. Past that we need hash marks up to the grouping // digits. Past that we need hash marks up to the grouping
// separator (and one beyond). // separator (and one beyond).
int total_digits = Math.max(minimumIntegerDigits, int total_digits = Math.max(minimumIntegerDigits,
groupingUsed ? groupingSize + 1: 0); groupingUsed ? groupingSize + 1: groupingSize);
for (int i = 0; i < total_digits - minimumIntegerDigits; ++i) for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
mainPattern.append(syms.getDigit()); mainPattern.append(syms.getDigit());
for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i) for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
@ -1022,11 +1114,16 @@ public class DecimalFormat extends NumberFormat
private boolean decimalSeparatorAlwaysShown; private boolean decimalSeparatorAlwaysShown;
private byte groupingSize; private byte groupingSize;
private byte minExponentDigits; private byte minExponentDigits;
private int exponentRound;
private int multiplier; private int multiplier;
private String negativePrefix; private String negativePrefix;
private String negativeSuffix; private String negativeSuffix;
private String positivePrefix; private String positivePrefix;
private String positiveSuffix; private String positiveSuffix;
private int[] negativePrefixRanges, positivePrefixRanges;
private HashMap[] negativePrefixAttrs, positivePrefixAttrs;
private int[] negativeSuffixRanges, positiveSuffixRanges;
private HashMap[] negativeSuffixAttrs, positiveSuffixAttrs;
private int serialVersionOnStream = 1; private int serialVersionOnStream = 1;
private DecimalFormatSymbols symbols; private DecimalFormatSymbols symbols;
private boolean useExponentialNotation; private boolean useExponentialNotation;