This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: java.text.DecimalFormat


Hi list,


I merged the attached patch from GNU classpath.


Michael


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.

Index: java/text/DecimalFormat.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/text/DecimalFormat.java,v
retrieving revision 1.15
diff -u -r1.15 DecimalFormat.java
--- java/text/DecimalFormat.java	20 Apr 2004 16:14:25 -0000	1.15
+++ java/text/DecimalFormat.java	4 May 2004 22:00:06 -0000
@@ -37,7 +37,13 @@
 
 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.HashMap;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
@@ -58,37 +64,48 @@
 {
   // This is a helper for applyPatternWithSymbols.  It reads a prefix
   // 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,
 			     boolean is_suffix)
   {
     int len = pattern.length();
-    buf.setLength(0);
+    boolean quoteStarted = false;
+    buf.clear();
+    
     boolean multiplierSet = false;
     while (index < len)
       {
 	char c = pattern.charAt(index);
+
+	if (quoteStarted)
+	  {
+	    if (c == '\'')
+	      quoteStarted = false;
+	    else
+	      buf.append(c);
+	    index++;
+	    continue;
+	  }
+
 	if (c == '\'' && index + 1 < len
 	    && pattern.charAt(index + 1) == '\'')
 	  {
 	    buf.append(c);
-	    ++index;
+	    index++;
 	  }
-	else if (c == '\'' && index + 2 < len
-		 && pattern.charAt(index + 2) == '\'')
+	else if (c == '\'')
 	  {
-	    buf.append(pattern.charAt(index + 1));
-	    index += 2;
+	    quoteStarted = true;
 	  }
 	else if (c == '\u00a4')
 	  {
 	    if (index + 1 < len && pattern.charAt(index + 1) == '\u00a4')
 	      {
-		buf.append(syms.getInternationalCurrencySymbol());
-		++index;
+		buf.append(syms.getInternationalCurrencySymbol(), NumberFormat.Field.CURRENCY);
+		index++;
 	      }
 	    else
-	      buf.append(syms.getCurrencySymbol());
+	      buf.append(syms.getCurrencySymbol(), NumberFormat.Field.CURRENCY);
 	  }
 	else if (c == syms.getPercent())
 	  {
@@ -97,7 +114,7 @@
 						  "- index: " + index);
 	    multiplierSet = true;
 	    multiplier = 100;
-	    buf.append(c);
+	    buf.append(c, NumberFormat.Field.PERCENT);
 	  }
 	else if (c == syms.getPerMill())
 	  {
@@ -106,7 +123,7 @@
 						  "- index: " + index);
 	    multiplierSet = true;
 	    multiplier = 1000;
-	    buf.append(c);
+	    buf.append(c, NumberFormat.Field.PERMILLE);
 	  }
 	else if (patChars.indexOf(c) != -1)
 	  {
@@ -115,9 +132,12 @@
 	  }
 	else
 	  buf.append(c);
-	++index;
+	index++;
       }
 
+    if (quoteStarted)
+      throw new IllegalArgumentException ("pattern is lacking a closing quote");
+
     return index;
   }
 
@@ -259,6 +279,16 @@
 	    useExponentialNotation = true;
 	    minExponentDigits = (byte) zeroCount;
 	  }
+
+	maximumIntegerDigits = groupingSize;
+	groupingSize = 0;
+	if (maximumIntegerDigits > minimumIntegerDigits && maximumIntegerDigits > 0)
+	  {
+	    minimumIntegerDigits = 1;
+	    exponentRound = maximumIntegerDigits;
+	  }
+	else
+	  exponentRound = 1;
       }
 
     return index;
@@ -304,17 +334,23 @@
     minimumFractionDigits = 0;
     minimumIntegerDigits = 1;
 
-    StringBuffer buf = new StringBuffer ();
+    AttributedFormatBuffer buf = new AttributedFormatBuffer ();
     String patChars = patternChars (syms);
 
     int max = pattern.length();
     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 = 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())
       {
@@ -329,14 +365,20 @@
 					      "expected - index: " + index);
 
 	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
 	// it side-effect this object.
 	index = scanFormat (pattern, index, patChars, syms, false);
 
 	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())
 	  throw new IllegalArgumentException ("end of pattern expected " +
@@ -409,39 +451,43 @@
 	    && useExponentialNotation == dup.useExponentialNotation);
   }
 
-  public StringBuffer format (double number, StringBuffer dest,
-			      FieldPosition fieldPos)
+  protected void formatInternal (double number, FormatBuffer dest,
+				 FieldPosition fieldPos)
   {
     // A very special case.
     if (Double.isNaN(number))
       {
 	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();
 	    fieldPos.setBeginIndex(index - symbols.getNaN().length());
 	    fieldPos.setEndIndex(index);
 	  }
-	return dest;
+	return;
       }
 
     boolean is_neg = number < 0;
     if (is_neg)
       {
 	if (negativePrefix != null)
-	  dest.append(negativePrefix);
+	  dest.append(negativePrefix, negativePrefixRanges, negativePrefixAttrs);
 	else
 	  {
-	    dest.append(symbols.getMinusSign());
-	    dest.append(positivePrefix);
+	    dest.append(symbols.getMinusSign(), NumberFormat.Field.SIGN);
+	    dest.append(positivePrefix, positivePrefixRanges, positivePrefixAttrs);
 	  }
 	number = - number;
       }
     else
-      dest.append(positivePrefix);
+      dest.append(positivePrefix, positivePrefixRanges, positivePrefixAttrs);
 
     int integerBeginIndex = dest.length();
     int integerEndIndex = 0;
+    int zeroStart = symbols.getZeroDigit() - '0';
+
     if (Double.isInfinite (number))
       {
 	dest.append(symbols.getInfinity());
@@ -457,6 +503,7 @@
 	if (useExponentialNotation)
 	  {
 	    exponent = (long) Math.floor (Math.log(number) / Math.log(10));
+	    exponent = exponent - (exponent % exponentRound);
 	    if (minimumIntegerDigits > 0)
 	      exponent -= minimumIntegerDigits - 1;
 	    baseNumber = (number / Math.pow(10.0, exponent));
@@ -468,33 +515,57 @@
 	baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);
 
 	int index = dest.length();
-	double intPart = Math.floor(baseNumber);
-	int count = 0;
-	while (count < maximumIntegerDigits
-	       && (intPart > 0 || count < minimumIntegerDigits))
+	//double intPart = Math.floor(baseNumber);
+	String intPart = Long.toString((long)Math.floor(baseNumber));
+	int count, groupPosition = intPart.length();
+
+	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);
-	    intPart = Math.floor(intPart / 10);
+	    int dig = intPart.charAt(count);
 
 	    // Append group separator if required.
-	    if (groupingUsed && count > 0 && groupingSize != 0 && count % groupingSize == 0)
-	      dest.insert(index, symbols.getGroupingSeparator());
-
-	    dest.insert(index, (char) (symbols.getZeroDigit() + dig));
+	    if (groupingUsed && count > 0 && groupingSize != 0 && groupPosition % groupingSize == 0)
+	      {
+		dest.append(symbols.getGroupingSeparator(), NumberFormat.Field.GROUPING_SEPARATOR);
+		dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
+	      }
+	    dest.append((char) (zeroStart + dig));
 
-	    ++count;
+	    groupPosition--;
 	  }
+	dest.setDefaultAttribute(null);
 
 	integerEndIndex = dest.length();
-
+	   
 	int decimal_index = integerEndIndex;
 	int consecutive_zeros = 0;
 	int total_digits = 0;
 
+	int localMaximumFractionDigits = maximumFractionDigits;
+
+	if (useExponentialNotation)
+	  localMaximumFractionDigits += minimumIntegerDigits - count;
+
 	// Strip integer part from NUMBER.
 	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;
-	     count < maximumFractionDigits
+	     count < localMaximumFractionDigits
 	       && (fracPart != 0 || count < minimumFractionDigits);
 	     ++count)
 	  {
@@ -517,61 +588,82 @@
 				    total_digits - minimumFractionDigits);
 	if (extra_zeros > 0)
 	  {
-	    dest.setLength(dest.length() - extra_zeros);
+	    dest.cutTail(extra_zeros);
 	    total_digits -= extra_zeros;
-	  }
-
-	// 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());
-	      }
+	    if (total_digits == 0 && !decimalSeparatorAlwaysShown)
+	      dest.cutTail(1);
 	  }
 
 	// Finally, print the exponent.
 	if (useExponentialNotation)
 	  {
-	    dest.append(symbols.getExponential());
+	    dest.append(symbols.getExponential(), NumberFormat.Field.EXPONENT_SYMBOL);	    
 	    if (exponent < 0)
 	      {
-		dest.append (symbols.getMinusSign ());
+		dest.append (symbols.getMinusSign (), NumberFormat.Field.EXPONENT_SIGN);
 		exponent = - exponent;
 	      }
 	    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;
-		 exponent > 0 || count < minExponentDigits;
+		 count < exponentString.length();
 		 ++count)
 	      {
-		long dig = exponent % 10;
-		exponent /= 10;
-		dest.insert(index, (char) (symbols.getZeroDigit() + dig));
+		int dig = exponentString.charAt(count);
+		dest.append((char) (zeroStart + dig));
 	      }
 	  }
       }
 
-    if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
+    if (fieldPos != null && 
+	(fieldPos.getField() == INTEGER_FIELD ||
+	 fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
       {
 	fieldPos.setBeginIndex(integerBeginIndex);
 	fieldPos.setEndIndex(integerEndIndex);
       }
 
-    dest.append((is_neg && negativeSuffix != null)
-		? negativeSuffix
-		: positiveSuffix);
+    if (is_neg && negativeSuffix != null)
+      dest.append(negativeSuffix, negativeSuffixRanges, negativeSuffixAttrs);
+    else
+      dest.append(positiveSuffix, positiveSuffixRanges, positiveSuffixAttrs);
+  }
+
+  public StringBuffer format (double number, StringBuffer dest,
+			      FieldPosition fieldPos)
+  {
+    formatInternal (number, new StringFormatBuffer(dest), fieldPos);
     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,
 			      FieldPosition fieldPos)
   {
     // If using exponential notation, we just format as a double.
     if (useExponentialNotation)
-      return format ((double) number, dest, fieldPos);
+       return format ((double) number, dest, fieldPos);
 
     boolean is_neg = number < 0;
     if (is_neg)
@@ -964,7 +1056,7 @@
     // digits.  Past that we need hash marks up to the grouping
     // separator (and one beyond).
     int total_digits = Math.max(minimumIntegerDigits,
-				groupingUsed ? groupingSize + 1: 0);
+				groupingUsed ? groupingSize + 1: groupingSize);
     for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
       mainPattern.append(syms.getDigit());
     for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
@@ -1022,11 +1114,16 @@
   private boolean decimalSeparatorAlwaysShown;
   private byte groupingSize;
   private byte minExponentDigits;
+  private int exponentRound;
   private int multiplier;
   private String negativePrefix;
   private String negativeSuffix;
   private String positivePrefix;
   private String positiveSuffix;
+  private int[] negativePrefixRanges, positivePrefixRanges;
+  private HashMap[] negativePrefixAttrs, positivePrefixAttrs;
+  private int[] negativeSuffixRanges, positiveSuffixRanges;
+  private HashMap[] negativeSuffixAttrs, positiveSuffixAttrs;
   private int serialVersionOnStream = 1;
   private DecimalFormatSymbols symbols;
   private boolean useExponentialNotation;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]