6898220: Optimize Formatter.parse (including String.printf)
authormartin
Thu, 05 Nov 2009 16:12:45 -0800
changeset 4185 8d87b7274c30
parent 4184 66ef929d58f2
child 4186 dccb7b436b13
child 4226 e7b2e4f305ca
6898220: Optimize Formatter.parse (including String.printf) Summary: Create fewer objects when parsing Reviewed-by: sherman Contributed-by: Daniel Martin <dtm@google.com>
jdk/src/share/classes/java/util/Formatter.java
--- a/jdk/src/share/classes/java/util/Formatter.java	Thu Nov 05 16:12:45 2009 -0800
+++ b/jdk/src/share/classes/java/util/Formatter.java	Thu Nov 05 16:12:45 2009 -0800
@@ -2485,55 +2485,45 @@
 
     private static Pattern fsPattern = Pattern.compile(formatSpecifier);
 
-    // Look for format specifiers in the format string.
+    /**
+     * Finds format specifiers in the format string.
+     */
     private FormatString[] parse(String s) {
-        ArrayList al = new ArrayList();
+        ArrayList<FormatString> al = new ArrayList<FormatString>();
         Matcher m = fsPattern.matcher(s);
-        int i = 0;
-        while (i < s.length()) {
+        for (int i = 0, len = s.length(); i < len; ) {
             if (m.find(i)) {
                 // Anything between the start of the string and the beginning
                 // of the format specifier is either fixed text or contains
                 // an invalid format string.
                 if (m.start() != i) {
                     // Make sure we didn't miss any invalid format specifiers
-                    checkText(s.substring(i, m.start()));
+                    checkText(s, i, m.start());
                     // Assume previous characters were fixed text
                     al.add(new FixedString(s.substring(i, m.start())));
                 }
 
-                // Expect 6 groups in regular expression
-                String[] sa = new String[6];
-                for (int j = 0; j < m.groupCount(); j++)
-                    {
-                    sa[j] = m.group(j + 1);
-//                  System.out.print(sa[j] + " ");
-                    }
-//              System.out.println();
-                al.add(new FormatSpecifier(this, sa));
+                al.add(new FormatSpecifier(m));
                 i = m.end();
             } else {
                 // No more valid format specifiers.  Check for possible invalid
                 // format specifiers.
-                checkText(s.substring(i));
+                checkText(s, i, len);
                 // The rest of the string is fixed text
                 al.add(new FixedString(s.substring(i)));
                 break;
             }
         }
-//      FormatString[] fs = new FormatString[al.size()];
-//      for (int j = 0; j < al.size(); j++)
-//          System.out.println(((FormatString) al.get(j)).toString());
-        return (FormatString[]) al.toArray(new FormatString[0]);
+        return al.toArray(new FormatString[al.size()]);
     }
 
-    private void checkText(String s) {
-        int idx;
-        // If there are any '%' in the given string, we got a bad format
-        // specifier.
-        if ((idx = s.indexOf('%')) != -1) {
-            char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
-            throw new UnknownFormatConversionException(String.valueOf(c));
+    private static void checkText(String s, int start, int end) {
+        for (int i = start; i < end; i++) {
+            // Any '%' found in the region starts an invalid format specifier.
+            if (s.charAt(i) == '%') {
+                char c = (i == end - 1) ? '%' : s.charAt(i + 1);
+                throw new UnknownFormatConversionException(String.valueOf(c));
+            }
         }
     }
 
@@ -2562,8 +2552,6 @@
         private boolean dt = false;
         private char c;
 
-        private Formatter formatter;
-
         // cache the line separator
         private String ls;
 
@@ -2650,21 +2638,22 @@
             return c;
         }
 
-        FormatSpecifier(Formatter formatter, String[] sa) {
-            this.formatter = formatter;
-            int idx = 0;
-
-            index(sa[idx++]);
-            flags(sa[idx++]);
-            width(sa[idx++]);
-            precision(sa[idx++]);
-
-            if (sa[idx] != null) {
+        FormatSpecifier(Matcher m) {
+            int idx = 1;
+
+            index(m.group(idx++));
+            flags(m.group(idx++));
+            width(m.group(idx++));
+            precision(m.group(idx++));
+
+            String tT = m.group(idx++);
+            if (tT != null) {
                 dt = true;
-                if (sa[idx].equals("T"))
+                if (tT.equals("T"))
                     f.add(Flags.UPPERCASE);
             }
-            conversion(sa[++idx]);
+
+            conversion(m.group(idx));
 
             if (dt)
                 checkDateTime();
@@ -2819,9 +2808,9 @@
 
         private void printString(Object arg, Locale l) throws IOException {
             if (arg instanceof Formattable) {
-                Formatter fmt = formatter;
-                if (formatter.locale() != l)
-                    fmt = new Formatter(formatter.out(), l);
+                Formatter fmt = Formatter.this;
+                if (fmt.locale() != l)
+                    fmt = new Formatter(fmt.out(), l);
                 ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
             } else {
                 if (f.contains(Flags.ALTERNATE))