2004-05-05 Guilhem Lavaux <guilhem@kaffe.org>
authorGuilhem Lavaux <guilhem@kaffe.org>
Wed, 5 May 2004 06:02:37 +0000 (06:02 +0000)
committerMichael Koch <mkoch@gcc.gnu.org>
Wed, 5 May 2004 06:02:37 +0000 (06:02 +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.

From-SVN: r81502

libjava/java/text/DecimalFormat.java

index 977acd8f92f7b5c7f654410617d2e41ec30d37d2..497a705670c4227e07309a73c255f3a836c50c3d 100644 (file)
@@ -330,7 +330,7 @@ public class DecimalFormat extends NumberFormat
     useExponentialNotation = false;
     groupingUsed = false;
     maximumFractionDigits = 0;
-    maximumIntegerDigits = 309;
+    maximumIntegerDigits = MAXIMUM_INTEGER_DIGITS;
     minimumFractionDigits = 0;
     minimumIntegerDigits = 1;
 
@@ -562,7 +562,7 @@ public class DecimalFormat extends NumberFormat
            dest.append (symbols.getDecimalSeparator(), NumberFormat.Field.DECIMAL_SEPARATOR);
          }
 
-
+       int fraction_begin = dest.length();
        dest.setDefaultAttribute(NumberFormat.Field.FRACTION);
        for (count = 0;
             count < localMaximumFractionDigits
@@ -594,6 +594,12 @@ public class DecimalFormat extends NumberFormat
              dest.cutTail(1);
          }
 
+       if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
+         {
+           fieldPos.setBeginIndex(fraction_begin);
+           fieldPos.setEndIndex(dest.length());
+         }
+
        // Finally, print the exponent.
        if (useExponentialNotation)
          {
@@ -793,14 +799,19 @@ public class DecimalFormat extends NumberFormat
 
   public Number parse (String str, ParsePosition pos)
   {
-    // Our strategy is simple: copy the text into a buffer,
-    // translating or omitting locale-specific information.  Then
-    // let Double or Long convert the number for us.
+    /*
+     * Our strategy is simple: copy the text into separate buffers: one for the int part,
+     * one for the fraction part and for the exponential part.
+     * We translate or omit locale-specific information.  
+     * If exponential is sufficiently big we merge the fraction and int part and
+     * remove the '.' and then we use Long to convert the number. In the other
+     * case, we use Double to convert the full number.
+     */
 
     boolean is_neg = false;
     int index = pos.getIndex();
-    StringBuffer buf = new StringBuffer ();
-
+    StringBuffer int_buf = new StringBuffer ();
+        
     // We have to check both prefixes, because one might be empty.  We
     // want to pick the longest prefix that matches.
     boolean got_pos = str.startsWith(positivePrefix, index);
@@ -840,11 +851,17 @@ public class DecimalFormat extends NumberFormat
     // FIXME: do we have to respect minimum digits?
     // What about leading zeros?  What about multiplier?
 
+    StringBuffer buf = int_buf;
+    StringBuffer frac_buf = null;
+    StringBuffer exp_buf = null;
     int start_index = index;
     int max = str.length();
-    int last = index + maximumIntegerDigits;
+    int exp_index = -1;
+    int last = index + MAXIMUM_INTEGER_DIGITS;
+
     if (last > 0 && max > last)
       max = last;
+
     char zero = symbols.getZeroDigit();
     int last_group = -1;
     boolean int_part = true;
@@ -863,12 +880,11 @@ public class DecimalFormat extends NumberFormat
                pos.setErrorIndex(index);
                return null;
              }
-           last_group = index;
+           last_group = index+1;
          }
        else if (c >= zero && c <= zero + 9)
          {
            buf.append((char) (c - zero + '0'));
-           exp_part = false;
          }
        else if (parseIntegerOnly)
          break;
@@ -881,14 +897,16 @@ public class DecimalFormat extends NumberFormat
                pos.setErrorIndex(index);
                return null;
              }
-           buf.append('.');
+           buf = frac_buf = new StringBuffer();
+           frac_buf.append('.');
            int_part = false;
          }
        else if (c == symbols.getExponential())
          {
-           buf.append('E');
+           buf = exp_buf = new StringBuffer();
            int_part = false;
            exp_part = true;
+           exp_index = index+1;
          }
        else if (exp_part
                 && (c == '+' || c == '-' || c == symbols.getMinusSign()))
@@ -932,16 +950,111 @@ public class DecimalFormat extends NumberFormat
       }
 
     String suffix = is_neg ? ns : positiveSuffix;
+    long multiplier = 1;
+    boolean use_long;
+
     if (is_neg)
-      buf.insert(0, '-');
+      int_buf.insert(0, '-');
+
+    // Now handle the exponential part if there is one.
+    if (exp_buf != null)
+      {
+       int exponent_value;
+
+       try
+         {
+           exponent_value = Integer.parseInt(exp_buf.toString());
+         }
+       catch (NumberFormatException x1)
+         {
+           pos.setErrorIndex(exp_index);
+           return null;
+         }
+
+       if (frac_buf == null)
+         {
+           // We only have to add some zeros to the int part.
+           // Build a multiplier.
+           for (int i = 0; i < exponent_value; i++)
+             int_buf.append('0');
+           
+           use_long = true;
+         }
+       else
+         {
+           boolean long_sufficient;
+
+           if (exponent_value < frac_buf.length()-1)
+             {
+               int lastNonNull = -1;
+               /* We have to check the fraction buffer: it may only be full of '0'
+                * or be sufficiently filled with it to convert the number into Long.
+                */
+               for (int i = 1; i < frac_buf.length(); i++)
+                 if (frac_buf.charAt(i) != '0')
+                   lastNonNull = i;
+
+               long_sufficient = (lastNonNull < 0 || lastNonNull <= exponent_value);
+             }
+           else
+             long_sufficient = true;
+           
+           if (long_sufficient)
+             {
+               for (int i = 1; i < frac_buf.length() && i < exponent_value; i++)
+                 int_buf.append(frac_buf.charAt(i));
+               for (int i = frac_buf.length()-1; i < exponent_value; i++)
+                 int_buf.append('0');
+               use_long = true;
+             }
+           else
+             {
+               /*
+                * A long type is not sufficient, we build the full buffer to
+                * be parsed by Double.
+                */
+               int_buf.append(frac_buf);
+               int_buf.append('E');
+               int_buf.append(exp_buf);
+               use_long = false;
+             }
+         }
+      }
+    else
+      {
+       if (frac_buf != null)
+         {
+           /* Check whether the fraction buffer contains only '0' */
+           int i;
+           for (i = 1; i < frac_buf.length(); i++)
+             if (frac_buf.charAt(i) != '0')
+               break;
+          
+           if (i != frac_buf.length())
+             {
+               use_long = false;
+               int_buf.append(frac_buf);
+             }
+           else
+             use_long = true;
+         }
+       else
+         use_long = true;
+      }
 
-    String t = buf.toString();
+    String t = int_buf.toString();
     Number result = null;
-    try
+    if (use_long)
       {
-       result = new Long (t);
+       try
+         {
+           result = new Long (t);
+         }
+       catch (NumberFormatException x1)
+         {
+         }
       }
-    catch (NumberFormatException x1)
+    else
       {
        try
          {
@@ -1110,6 +1223,8 @@ public class DecimalFormat extends NumberFormat
     return computePattern (nonLocalizedSymbols);
   }
 
+  private static final int MAXIMUM_INTEGER_DIGITS = 309; 
+
   // These names are fixed by the serialization spec.
   private boolean decimalSeparatorAlwaysShown;
   private byte groupingSize;