2004-05-05 Guilhem Lavaux <guilhem@kaffe.org>
authorGuilhem Lavaux <guilhem@kaffe.org>
Tue, 4 May 2004 22:00:30 +0000 (22:00 +0000)
committerMichael Koch <mkoch@gcc.gnu.org>
Tue, 4 May 2004 22:00:30 +0000 (22:00 +0000)
* 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

libjava/ChangeLog
libjava/java/text/DecimalFormat.java

index 88441aa135a5b8dd376fc360d5929c8c47439467..91080fffb80857bfa8513f2ad319f2a6bf9bcae8 100644 (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>
 
        * java/security/interfaces/DSAKeyPairGenerator.java,
index 2f6691a85313ec398da6ebf19c60e544864159e3..977acd8f92f7b5c7f654410617d2e41ec30d37d2 100644 (file)
@@ -37,7 +37,13 @@ exception statement from your version. */
 
 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 @@ public class DecimalFormat extends NumberFormat
 {
   // 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 @@ public class DecimalFormat extends NumberFormat
                                                  "- index: " + index);
            multiplierSet = true;
            multiplier = 100;
-           buf.append(c);
+           buf.append(c, NumberFormat.Field.PERCENT);
          }
        else if (c == syms.getPerMill())
          {
@@ -106,7 +123,7 @@ public class DecimalFormat extends NumberFormat
                                                  "- 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 @@ public class DecimalFormat extends NumberFormat
          }
        else
          buf.append(c);
-       ++index;
+       index++;
       }
 
+    if (quoteStarted)
+      throw new IllegalArgumentException ("pattern is lacking a closing quote");
+
     return index;
   }
 
@@ -259,6 +279,16 @@ public class DecimalFormat extends NumberFormat
            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 @@ public class DecimalFormat extends NumberFormat
     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 @@ public class DecimalFormat extends NumberFormat
                                              "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 @@ public class DecimalFormat extends NumberFormat
            && 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 @@ public class DecimalFormat extends NumberFormat
        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 @@ public class DecimalFormat extends NumberFormat
        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 @@ public class DecimalFormat extends NumberFormat
                                    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 @@ public class DecimalFormat extends NumberFormat
     // 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 @@ public class DecimalFormat extends NumberFormat
   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;