You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by jw...@apache.org on 2007/05/30 18:46:25 UTC

svn commit: r542870 - in /myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal: skin/SkinCSSParser.java skin/SkinStyleSheetParserUtils.java style/util/CSSGenerationUtils.java

Author: jwaldman
Date: Wed May 30 09:46:24 2007
New Revision: 542870

URL: http://svn.apache.org/viewvc?view=rev&rev=542870
Log:
improve performance of skin parsing by not using regexp to split on spaces, commas, semi-colons.
In some cases I keep the regexp, but I compile the Pattern in a constant instead of calling String's
split.

Modified:
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinCSSParser.java
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleSheetParserUtils.java
    myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSGenerationUtils.java

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinCSSParser.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinCSSParser.java?view=diff&rev=542870&r1=542869&r2=542870
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinCSSParser.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinCSSParser.java Wed May 30 09:46:24 2007
@@ -109,9 +109,10 @@
 
     List<String> selectorList = new ArrayList<String>();
 
-    // pull apart by the regexp that means
-    // (zero or more whitespace) then (comma) then (zero or more whitespace)
-    String[] selector = selectors.split("\\s*,\\s*");
+    // pull apart by commas
+    // don't skip whitespace since whitespace means descendant selectors in css
+    String[] selector = _splitString(selectors, ',', false);
+
     String trimmedSelector;
     for (int i=0; i < selector.length; i++)
     {
@@ -146,9 +147,9 @@
     // first, parse out any comments
     Matcher matcher = _COMMENT_PATTERN.matcher(properties);
     properties = matcher.replaceAll("");
-       
-    String[] property = properties.split("\\s*;\\s*");
-
+    // split into name and value (skip whitespace)
+    String[] property = _splitString(properties, ';', true);    
+    
     for (int i=0; i < property.length; i++)
     {
       int indexOfColon = property[i].indexOf(':');
@@ -156,15 +157,58 @@
       {
         String name = property[i].substring(0, indexOfColon);
         String value = property[i].substring(indexOfColon+1);
-        _documentHandler.property((name.trim()), value.trim());
+        _documentHandler.property((name), value);
 
       }
     }
-
-
   }
 
-  private static String _trimChar(
+  /**
+   * return the array of strings computed by splitting this string
+   * around matches of the given character
+   * @param in
+   * @param charDelimiter
+   * @param skipWhitespace if true, whitespace is skipped and not included in the return Strings
+   * in the String array.
+   * @return String[] The array of Strings computed by splitting the input String
+   * around matches of the charDelimiter
+   */
+  private static String[] _splitString (
+    String  in, 
+    char    charDelimiter,
+    boolean skipWhitespace)
+  {   
+    // return a String[] with each piece that is deliminated by the inChar.
+    int length = in.length();
+    StringBuffer buffer = new StringBuffer(length);
+    List<String> splitList = new ArrayList<String>();
+    
+    for (int i=0; i < length; i++)
+    {
+      char c = in.charAt(i);
+      if (c == charDelimiter)
+      {
+        // we hit the delimiter, so put it in the splitList and start a new buffer.
+        splitList.add(buffer.toString());
+        buffer = new StringBuffer(length);
+      }
+      else 
+      {
+        // it's ok to put the character in the buffer if we don't want to skip whitespace
+        // or if it isn't whitespace to begin with.
+        if (!skipWhitespace || !(Character.isWhitespace(c)))
+          buffer.append(c);
+      }
+      
+    }
+    // we are done with all the characters
+    String lastString = buffer.toString();
+    if (lastString.length() > 0)
+      splitList.add(lastString);
+    return splitList.toArray(_EMPTY_STRING_ARRAY);
+  }
+  
+  private static String _trimChar (
     String in,
     char   c)
   {
@@ -451,6 +495,9 @@
   // comments from the properties, and we use this pattern to do it.
   private static final Pattern  _COMMENT_PATTERN = 
      Pattern.compile("(?s)/\\*.*?\\*/"); 
+     
+  private static final String[] _EMPTY_STRING_ARRAY = new String[0];
+
      
   private static final TrinidadLogger _LOG = 
     TrinidadLogger.createTrinidadLogger(SkinCSSParser.class);

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleSheetParserUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleSheetParserUtils.java?view=diff&rev=542870&r1=542869&r2=542870
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleSheetParserUtils.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/skin/SkinStyleSheetParserUtils.java Wed May 30 09:46:24 2007
@@ -34,6 +34,8 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import java.util.regex.Pattern;
+
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 
 import org.apache.myfaces.trinidadinternal.share.io.InputStreamProvider;
@@ -369,7 +371,7 @@
           }
           else if (propertyNameSuffix.equals(_PROPERTY_INHIBIT))
           {
-            for (String value : propertyValue.split("\\s"))
+            for (String value : _SPACE_PATTERN.split(propertyValue))
             {
               inhibitedPropertySet.add(value);
             }
@@ -662,7 +664,8 @@
       // if it ends with :alias, it is a namedstyle.
 
       List<String> selectors = new ArrayList<String>();
-      String[] test = value.split("selector\\(");
+      
+      String[] test = _SELECTOR_PATTERN.split(value);
       for (int i=0; i < test.length; i++)
       {
         int endIndex = test[i].indexOf(")");
@@ -898,6 +901,9 @@
   private static final String _PROPERTY_RULE_REF = "rule-ref";
   private static final String _PROPERTY_INHIBIT = "inhibit";
   private static final String _PROPERTY_TEXT_ANTIALIAS = "text-antialias";
+  
+  private static final Pattern _SPACE_PATTERN = Pattern.compile("\\s"); 
+  private static final Pattern _SELECTOR_PATTERN = Pattern.compile("selector\\(");
 
 
   static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(

Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSGenerationUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSGenerationUtils.java?view=diff&rev=542870&r1=542869&r2=542870
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSGenerationUtils.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/style/util/CSSGenerationUtils.java Wed May 30 09:46:24 2007
@@ -31,8 +31,11 @@
 import java.util.Set;
 import java.util.Vector;
 
+import java.util.regex.Pattern;
+
 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
 import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent;
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.OutputUtils;
 import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SkinSelectors;
 import org.apache.myfaces.trinidadinternal.style.StyleContext;
 import org.apache.myfaces.trinidadinternal.style.xml.parse.PropertyNode;
@@ -234,7 +237,7 @@
 
             if (_hasNamespacePrefix(shortSelector, namespacePrefixArray))
             {
-              String[] shortSelectorArray  = shortSelector.split("\\s");
+              String[] shortSelectorArray  = _splitStringByWhitespace(shortSelector);
 
               shortSelector =
                 _getMappedNSSelector(shortStyleClassMap,
@@ -459,7 +462,7 @@
     // now find each af| component selector and map
     // e.g., af|menuPath::step maps to af|menuPath A
 
-    // split the string into the spaces
+    // order the pseudo elements and classes
     String base = selector.substring(afIndex);
     String[] afSelectors =
         _orderPseudoElementsAndClasses(base);
@@ -502,8 +505,7 @@
         if (namespaceIndex > -1)
         {
           // get the selector up until the space.
-          String[] baseSelector =
-            (mappedSelector.substring(namespaceIndex)).split("\\s");
+          String[] baseSelector = _splitStringByWhitespace(mappedSelector.substring(namespaceIndex));
           afComponentSelector = baseSelector[0];
           afSelectorList.add(afComponentSelector);
         }
@@ -759,11 +761,12 @@
     }
     else
     {
-      // there are no namespaces in this selector. TODO We still need to convert the pseudo-classes
+      // there are no namespaces in this selector.
       mappedSelector = _convertPseudoClassesInSelector(selector);
     }
     return mappedSelector;
   }
+
   /**
    * Runs a namespaced selector through a map.
    * This could be a map to convert the
@@ -918,6 +921,7 @@
     String   selector,
     String[] nsPrefixArray)
   {
+    if (selector == null) return false;
     boolean hasNamespacePrefix = false;
     int numNamespaces = nsPrefixArray.length;
     for (int i=0; (i <  numNamespaces )&& !hasNamespacePrefix; i++)
@@ -967,7 +971,7 @@
   private static String[]  _orderPseudoElementsAndClasses(
     String selector)
   {
-    String[] input = selector.split("\\s");
+    String[] input = _splitStringByWhitespace(selector);
 
     List<String> output = new ArrayList<String>();
     for (int i=0; i < input.length; i++)
@@ -1042,7 +1046,7 @@
       return selector;
 
     // split on spaces.
-    String[] spacerArray = selector.split("\\s");
+    String[] spacerArray = _splitStringByWhitespace(selector);
 
     for (int i=0; i < spacerArray.length; i++)
     {
@@ -1199,6 +1203,59 @@
     return completeBuffer.toString();
   }
 
+  /**
+   * return the array of strings computed by splitting this string
+   * around one or more whitespaces This calls Character.isWhitespace to determine if it is
+   * whitespace. This is important because tabs, newlines, etc count as whitespace
+   * in the selector strings. This is faster than String's split("\\s")
+   * @param selector
+   * @return String[] The array of Strings computed by splitting the input String
+   * around one or more spaces. e.g, "af|foo    af|bar" returns "af|foo" and "af|bar" in
+   * a String Array.
+   */
+  private static String[] _splitStringByWhitespace (
+    String  selector)
+  {
+    // return a String[] with each piece that is deliminated by the inChar.
+    int length = selector.length();
+    StringBuffer buffer = new StringBuffer(length);
+    List<String> splitList = new ArrayList<String>();
+    boolean inWhitespace = false;
+
+    for (int i=0; i < length; i++)
+    {
+      char c = selector.charAt(i);
+      if (Character.isWhitespace(c))
+      {
+        // we hit the whitespace delimiter, so put it in the splitList and start a new buffer.
+        // ignore spaces that are in a row
+        if (!inWhitespace)
+        {
+          String bufferString = buffer.toString();
+          if (bufferString.length() > 0)
+          {
+            splitList.add(bufferString);
+            buffer = new StringBuffer(length);
+            inWhitespace = true;
+          }
+        }
+      }
+      else
+      {
+        buffer.append(c);
+        if (inWhitespace)
+          inWhitespace = false;
+      }
+    }
+    // we are done with all the characters
+    String lastString = buffer.toString();
+    if (lastString.length() > 0)
+      splitList.add(lastString);
+
+    return splitList.toArray(_EMPTY_STRING_ARRAY);      
+
+  }
+
   // run through the map. If it's not in the map, return the selector unchanged.
   private static String _runThroughMap(Map<String, String> map, String selector)
   {
@@ -1247,7 +1304,7 @@
     builder.append(".");
     builder.append(SkinSelectors.STATE_PREFIX);
 
-    for (String content : pseudoClass.substring(1).split("-"))
+    for (String content : _DASH_PATTERN.split(pseudoClass.substring(1)))
     {
       if (content.length() > 0)
       {
@@ -1273,6 +1330,9 @@
     _BUILT_IN_PSEUDO_CLASSES.add(":focus");
   }
 
+  private static final Pattern _SPACE_PATTERN = Pattern.compile("\\s");
+  private static final Pattern _DASH_PATTERN =  Pattern.compile("-");
+  private static final String[] _EMPTY_STRING_ARRAY = new String[0];
 
   private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(CSSGenerationUtils.class);
 }