classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

java.text.DecimalFormat.parse() patch


From: Guilhem Lavaux
Subject: java.text.DecimalFormat.parse() patch
Date: Sat, 01 May 2004 13:44:09 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030630

Hi,

Here is a patch which fixes 3 old failures on mauve and maybe 2 or 3 new because of the updated mauve test.

This fixes handling of exponentiation notation, grouping handling and better handling of Long and Double types.

ChangeLog entry:

2004-05-01  Guilhem Lavaux <address@hidden>

        * 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.
Index: java/text/DecimalFormat.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/text/DecimalFormat.java,v
retrieving revision 1.14
diff -u -b -B -r1.14 DecimalFormat.java
--- java/text/DecimalFormat.java        28 Apr 2004 19:17:08 -0000      1.14
+++ java/text/DecimalFormat.java        1 May 2004 11:30:47 -0000
@@ -328,7 +328,7 @@
     useExponentialNotation = false;
     groupingUsed = false;
     maximumFractionDigits = 0;
-    maximumIntegerDigits = 309;
+    maximumIntegerDigits = MAXIMUM_INTEGER_DIGITS;
     minimumFractionDigits = 0;
     minimumIntegerDigits = 1;
 
@@ -560,7 +560,7 @@
            dest.append (symbols.getDecimalSeparator(), 
NumberFormat.Field.DECIMAL_SEPARATOR);
          }
 
-
+       int fraction_begin = dest.length();
        dest.setDefaultAttribute(NumberFormat.Field.FRACTION);
        for (count = 0;
             count < localMaximumFractionDigits
@@ -592,6 +592,12 @@
              dest.cutTail(1);
          }
 
+       if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
+         {
+           fieldPos.setBeginIndex(fraction_begin);
+           fieldPos.setEndIndex(dest.length());
+         }
+
        // Finally, print the exponent.
        if (useExponentialNotation)
          {
@@ -791,13 +797,18 @@
 
   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.
@@ -838,11 +849,17 @@
     // 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;
@@ -861,12 +878,11 @@
                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;
@@ -879,14 +895,16 @@
                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()))
@@ -930,17 +948,112 @@
       }
 
     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;
 
-    String t = buf.toString();
+               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 = int_buf.toString();
     Number result = null;
+    if (use_long)
+      {
     try
       {
        result = new Long (t);
       }
     catch (NumberFormatException x1)
       {
+         }
+      }
+    else
+      {
        try
          {
            result = new Double (t);
@@ -1107,6 +1220,8 @@
   {
     return computePattern (nonLocalizedSymbols);
   }
+
+  private static final int MAXIMUM_INTEGER_DIGITS = 309; 
 
   // These names are fixed by the serialization spec.
   private boolean decimalSeparatorAlwaysShown;

Attachment: pgps6kJI7Vti1.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]