changeset 10647:42cf719516d0

8055055: Improve numeric parsing in java.sql Reviewed-by: lancea
author redestad
date Wed, 13 Aug 2014 18:40:16 +0200
parents 99230080fada
children 267950e85a3b
files src/java.sql/share/classes/java/sql/Date.java src/java.sql/share/classes/java/sql/Time.java src/java.sql/share/classes/java/sql/Timestamp.java
diffstat 3 files changed, 55 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.sql/share/classes/java/sql/Date.java	Fri Sep 12 15:51:22 2014 +0100
+++ b/src/java.sql/share/classes/java/sql/Date.java	Wed Aug 13 18:40:16 2014 +0200
@@ -108,31 +108,27 @@
      *         JDBC date escape format (yyyy-[m]m-[d]d)
      */
     public static Date valueOf(String s) {
+        if (s == null) {
+            throw new java.lang.IllegalArgumentException();
+        }
         final int YEAR_LENGTH = 4;
         final int MONTH_LENGTH = 2;
         final int DAY_LENGTH = 2;
         final int MAX_MONTH = 12;
         final int MAX_DAY = 31;
-        int firstDash;
-        int secondDash;
         Date d = null;
-        if (s == null) {
-            throw new java.lang.IllegalArgumentException();
-        }
 
-        firstDash = s.indexOf('-');
-        secondDash = s.indexOf('-', firstDash + 1);
+        int firstDash = s.indexOf('-');
+        int secondDash = s.indexOf('-', firstDash + 1);
+        int len = s.length();
 
-        if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
-            String yyyy = s.substring(0, firstDash);
-            String mm = s.substring(firstDash + 1, secondDash);
-            String dd = s.substring(secondDash + 1);
-            if (yyyy.length() == YEAR_LENGTH &&
-                    (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
-                    (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
-                int year = Integer.parseInt(yyyy);
-                int month = Integer.parseInt(mm);
-                int day = Integer.parseInt(dd);
+        if ((firstDash > 0) && (secondDash > 0) && (secondDash < len - 1)) {
+            if (firstDash == YEAR_LENGTH &&
+                    (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) &&
+                    (len - secondDash > 1 && len - secondDash <= DAY_LENGTH + 1)) {
+                int year = Integer.parseInt(s, 0, firstDash, 10);
+                int month = Integer.parseInt(s, firstDash + 1, secondDash, 10);
+                int day = Integer.parseInt(s, secondDash + 1, len, 10);
 
                 if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
                     d = new Date(year - 1900, month - 1, day);
--- a/src/java.sql/share/classes/java/sql/Time.java	Fri Sep 12 15:51:22 2014 +0100
+++ b/src/java.sql/share/classes/java/sql/Time.java	Wed Aug 13 18:40:16 2014 +0200
@@ -90,22 +90,19 @@
      * @return a corresponding <code>Time</code> object
      */
     public static Time valueOf(String s) {
+        if (s == null) throw new java.lang.IllegalArgumentException();
+
         int hour;
         int minute;
         int second;
-        int firstColon;
-        int secondColon;
-
-        if (s == null) throw new java.lang.IllegalArgumentException();
-
-        firstColon = s.indexOf(':');
-        secondColon = s.indexOf(':', firstColon+1);
-        if ((firstColon > 0) & (secondColon > 0) &
-            (secondColon < s.length()-1)) {
-            hour = Integer.parseInt(s.substring(0, firstColon));
-            minute =
-                Integer.parseInt(s.substring(firstColon+1, secondColon));
-            second = Integer.parseInt(s.substring(secondColon+1));
+        int firstColon = s.indexOf(':');
+        int secondColon = s.indexOf(':', firstColon + 1);
+        int len = s.length();
+        if (firstColon > 0 && secondColon > 0 &&
+                secondColon < len - 1) {
+            hour = Integer.parseInt(s, 0, firstColon, 10);
+            minute = Integer.parseInt(s, firstColon + 1, secondColon, 10);
+            second = Integer.parseInt(s, secondColon + 1, len, 10);
         } else {
             throw new java.lang.IllegalArgumentException();
         }
--- a/src/java.sql/share/classes/java/sql/Timestamp.java	Fri Sep 12 15:51:22 2014 +0100
+++ b/src/java.sql/share/classes/java/sql/Timestamp.java	Wed Aug 13 18:40:16 2014 +0200
@@ -171,9 +171,6 @@
         final int DAY_LENGTH = 2;
         final int MAX_MONTH = 12;
         final int MAX_DAY = 31;
-        String date_s;
-        String time_s;
-        String nanos_s;
         int year = 0;
         int month = 0;
         int day = 0;
@@ -184,49 +181,38 @@
         int firstDash;
         int secondDash;
         int dividingSpace;
-        int firstColon = 0;
-        int secondColon = 0;
-        int period = 0;
+        int firstColon;
+        int secondColon;
+        int period;
         String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]";
-        String zeros = "000000000";
-        String delimiterDate = "-";
-        String delimiterTime = ":";
 
         if (s == null) throw new java.lang.IllegalArgumentException("null string");
 
         // Split the string into date and time components
         s = s.trim();
         dividingSpace = s.indexOf(' ');
-        if (dividingSpace > 0) {
-            date_s = s.substring(0,dividingSpace);
-            time_s = s.substring(dividingSpace+1);
-        } else {
+        if (dividingSpace < 0) {
             throw new java.lang.IllegalArgumentException(formatError);
         }
 
         // Parse the date
-        firstDash = date_s.indexOf('-');
-        secondDash = date_s.indexOf('-', firstDash+1);
+        firstDash = s.indexOf('-');
+        secondDash = s.indexOf('-', firstDash+1);
 
         // Parse the time
-        if (time_s == null)
-            throw new java.lang.IllegalArgumentException(formatError);
-        firstColon = time_s.indexOf(':');
-        secondColon = time_s.indexOf(':', firstColon+1);
-        period = time_s.indexOf('.', secondColon+1);
+        firstColon = s.indexOf(':', dividingSpace + 1);
+        secondColon = s.indexOf(':', firstColon + 1);
+        period = s.indexOf('.', secondColon + 1);
 
         // Convert the date
         boolean parsedDate = false;
-        if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
-            String yyyy = date_s.substring(0, firstDash);
-            String mm = date_s.substring(firstDash + 1, secondDash);
-            String dd = date_s.substring(secondDash + 1);
-            if (yyyy.length() == YEAR_LENGTH &&
-                    (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
-                    (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
-                 year = Integer.parseInt(yyyy);
-                 month = Integer.parseInt(mm);
-                 day = Integer.parseInt(dd);
+        if (firstDash > 0 && secondDash > 0 && secondDash < dividingSpace - 1) {
+            if (firstDash == YEAR_LENGTH &&
+                    (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) &&
+                    (dividingSpace - secondDash > 1 && dividingSpace - secondDash <= DAY_LENGTH + 1)) {
+                 year = Integer.parseInt(s, 0, firstDash, 10);
+                 month = Integer.parseInt(s, firstDash + 1, secondDash, 10);
+                 day = Integer.parseInt(s, secondDash + 1, dividingSpace, 10);
 
                 if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
                     parsedDate = true;
@@ -238,25 +224,27 @@
         }
 
         // Convert the time; default missing nanos
-        if ((firstColon > 0) & (secondColon > 0) &
-            (secondColon < time_s.length()-1)) {
-            hour = Integer.parseInt(time_s.substring(0, firstColon));
-            minute =
-                Integer.parseInt(time_s.substring(firstColon+1, secondColon));
-            if ((period > 0) & (period < time_s.length()-1)) {
-                second =
-                    Integer.parseInt(time_s.substring(secondColon+1, period));
-                nanos_s = time_s.substring(period+1);
-                if (nanos_s.length() > 9)
+        int len = s.length();
+        if (firstColon > 0 && secondColon > 0 && secondColon < len - 1) {
+            hour = Integer.parseInt(s, dividingSpace + 1, firstColon, 10);
+            minute = Integer.parseInt(s, firstColon + 1, secondColon, 10);
+            if (period > 0 && period < len - 1) {
+                second = Integer.parseInt(s, secondColon + 1, period, 10);
+                int nanoPrecision = len - (period + 1);
+                if (nanoPrecision > 9)
                     throw new java.lang.IllegalArgumentException(formatError);
-                if (!Character.isDigit(nanos_s.charAt(0)))
+                if (!Character.isDigit(s.charAt(period + 1)))
                     throw new java.lang.IllegalArgumentException(formatError);
-                nanos_s = nanos_s + zeros.substring(0,9-nanos_s.length());
-                a_nanos = Integer.parseInt(nanos_s);
+                int tmpNanos = Integer.parseInt(s, period + 1, len, 10);
+                while (nanoPrecision < 9) {
+                    tmpNanos *= 10;
+                    nanoPrecision++;
+                }
+                a_nanos = tmpNanos;
             } else if (period > 0) {
                 throw new java.lang.IllegalArgumentException(formatError);
             } else {
-                second = Integer.parseInt(time_s.substring(secondColon+1));
+                second = Integer.parseInt(s, secondColon + 1, len, 10);
             }
         } else {
             throw new java.lang.IllegalArgumentException(formatError);