]> granicus.if.org Git - icu/commitdiff
ICU-9641 Add customizable max parse digit to DecimalFormat
authorMichael Ow <mow@svn.icu-project.org>
Wed, 19 Dec 2012 01:23:53 +0000 (01:23 +0000)
committerMichael Ow <mow@svn.icu-project.org>
Wed, 19 Dec 2012 01:23:53 +0000 (01:23 +0000)
X-SVN-Rev: 32993

icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java

index baefca8e34f6d2b6ef97277212e8213109cd3c08..bf9fbb479cf35bf8addb1424919896756d1d1156 100644 (file)
@@ -2152,9 +2152,9 @@ public class DecimalFormat extends NumberFormat {
     // When parsing a number with big exponential value, it requires to transform the
     // value into a string representation to construct BigInteger instance.  We want to
     // set the maximum size because it can easily trigger OutOfMemoryException.
-    // PARSE_MAX_EXPONENT is currently set to 1000, which is much bigger than MAX_VALUE of
-    // Double ( See the problem reported by ticket#5698
-    private static final int PARSE_MAX_EXPONENT = 1000;
+    // PARSE_MAX_EXPONENT is currently set to 1000 (See getParseMaxDigits()),
+    // which is much bigger than MAX_VALUE of Double ( See the problem reported by ticket#5698
+    private int PARSE_MAX_EXPONENT = 1000;
 
     /**
      * Parses the given text into a number. The text is parsed beginning at parsePosition,
@@ -2499,9 +2499,9 @@ public class DecimalFormat extends NumberFormat {
 
             // Adjust for exponent, if any
             exponent += digits.decimalAt;
-            if (exponent < -PARSE_MAX_EXPONENT) {
+            if (exponent < -getParseMaxDigits()) {
                 status[STATUS_UNDERFLOW] = true;
-            } else if (exponent > PARSE_MAX_EXPONENT) {
+            } else if (exponent > getParseMaxDigits()) {
                 status[STATUS_INFINITE] = true;
             } else {
                 digits.decimalAt = (int) exponent;
@@ -5057,6 +5057,29 @@ public class DecimalFormat extends NumberFormat {
     public boolean isParseBigDecimal() {
         return parseBigDecimal;
     }
+    
+    /**
+    * Set the maximum number of exponent digits when parsing a number. 
+    * If the limit is set too high, an OutOfMemoryException may be triggered.
+    * The default value is 1000.
+    * @param newValue the new limit
+    * @draft ICU 51
+    */
+    public void setParseMaxDigits(int newValue) {
+        if (newValue > 0) {
+            PARSE_MAX_EXPONENT = newValue;
+        }
+    }
+    
+    /**
+    * Get the current maximum number of exponent digits when parsing a
+    * number.
+    *
+    * @draft ICU 51
+    */
+    public int getParseMaxDigits() {
+        return PARSE_MAX_EXPONENT;
+    }
 
     private void writeObject(ObjectOutputStream stream) throws IOException {
         // Ticket#6449 Format.Field instances are not serializable. When
index 49547c3a46cd69ace81d55b10e7157838d32a744..339aa8ba91edddf4726c5f49eb4d7683552e972f 100644 (file)
@@ -3039,6 +3039,33 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
             }
         }
     }
+    
+    public void TestParseMaxDigits() {
+        DecimalFormat fmt = new DecimalFormat();
+        String number = "100000000000";
+        int newParseMax = number.length() - 1;
+        
+        fmt.setParseMaxDigits(-1);
+        
+        /* Default value is 1000 */
+        if (fmt.getParseMaxDigits() != 1000) {
+            errln("Fail valid value checking in setParseMaxDigits.");
+        }
+        
+        try {
+            if (fmt.parse(number).doubleValue() == Float.POSITIVE_INFINITY) {
+                errln("Got Infinity but should NOT when parsing number: " + number);
+            }
+            
+            fmt.setParseMaxDigits(newParseMax);
+            
+            if (fmt.parse(number).doubleValue() != Float.POSITIVE_INFINITY) {
+                errln("Did not get Infinity but should when parsing number: " + number);
+            }
+        } catch (ParseException ex) {
+            
+        }
+    }
 
     private static class FormatCharItrTestThread implements Runnable {
         private final NumberFormat fmt;