[FELIX-4820] Optimize version range parsing a bit

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1663615 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/utils/src/main/java/org/apache/felix/utils/version/VersionCleaner.java b/utils/src/main/java/org/apache/felix/utils/version/VersionCleaner.java
index 4b2078b..d9f89d6 100644
--- a/utils/src/main/java/org/apache/felix/utils/version/VersionCleaner.java
+++ b/utils/src/main/java/org/apache/felix/utils/version/VersionCleaner.java
@@ -42,6 +42,11 @@
         {
             return "0.0.0";
         }
+        String clean = fastSyntax(version);
+        if (clean != null)
+        {
+            return clean;
+        }
         StringBuffer result = new StringBuffer();
         Matcher m = FUZZY_VERSION.matcher(version);
         if (m.matches())
@@ -108,4 +113,45 @@
         }
     }
 
+    private static String fastSyntax(String version) {
+        int state = 0;
+        for (int i = 0, l = version.length(); i < l; i++) {
+            char ch = version.charAt(i);
+            switch (state) {
+            case 0:
+            case 2:
+            case 4:
+                if (ch < '0' || ch > '9') {
+                    return null;
+                }
+                state++;
+                break;
+            case 1:
+            case 3:
+            case 5:
+                if (ch == '.') {
+                    state++;
+                } else if (ch < '0' || ch > '9') {
+                    return null;
+                }
+                break;
+            case 6:
+                if (ch == '.') {
+                    return null;
+                }
+                break;
+            }
+        }
+        switch (state) {
+        case 0:
+        case 1:
+            return version + ".0.0";
+        case 2:
+        case 3:
+            return version + ".0";
+        default:
+            return version;
+        }
+    }
+
 }
diff --git a/utils/src/main/java/org/apache/felix/utils/version/VersionRange.java b/utils/src/main/java/org/apache/felix/utils/version/VersionRange.java
index 5379665..c2279ca 100644
--- a/utils/src/main/java/org/apache/felix/utils/version/VersionRange.java
+++ b/utils/src/main/java/org/apache/felix/utils/version/VersionRange.java
@@ -101,8 +101,7 @@
 
     public VersionRange( String val, boolean exact, boolean clean ) throws IllegalArgumentException, NumberFormatException
     {
-        val = val.replaceAll( "\\s", "" );
-        val = val.replaceAll( "\"", "" );
+        val = removeQuotesAndWhitespaces(val);
         int fst = val.charAt( 0 );
         if ( fst == '[' )
         {
@@ -136,17 +135,53 @@
                 + ": range must end in ')' or ']'" );
         }
 
-        String inner = val.substring( 1, val.length() - 1 );
-        String[] floorCeiling = inner.split( "," );
-        if ( floorCeiling.length != 2 )
+        int comma = val.indexOf( ',' );
+        if ( comma < 0 )
+        {
+            throw new IllegalArgumentException( "illegal version range syntax " + "no comma" );
+        }
+        if ( val.indexOf( ',', comma + 1 ) > 0 )
         {
             throw new IllegalArgumentException( "illegal version range syntax " + "too many commas" );
         }
-        floor = VersionTable.getVersion( floorCeiling[0], clean );
-        ceiling = "*".equals( floorCeiling[1] ) ? INFINITE_VERSION : VersionTable.getVersion( floorCeiling[1], clean );
+        String strFloor = val.substring( 1, comma );
+        String strCeil = val.substring( comma + 1, val.length() - 1 );
+        floor = VersionTable.getVersion( strFloor, clean );
+        ceiling = "*".equals( strCeil ) ? INFINITE_VERSION : VersionTable.getVersion( strCeil, clean );
         checkRange();
     }
 
+    private String removeQuotesAndWhitespaces(String val) {
+        for (int i = 0, l = val.length(); i < l; i++) {
+            char ch = val.charAt(i);
+            if (isRemoveable(ch)) {
+                StringBuilder sb = new StringBuilder(l);
+                sb.append(val, 0, i);
+                for (i++; i < l; i++) {
+                    ch = val.charAt(i);
+                    if (!isRemoveable(ch)) {
+                        sb.append(ch);
+                    }
+                }
+                return sb.toString();
+            }
+        }
+        return val;
+    }
+
+    private static boolean[] removeable;
+    static {
+        removeable = new boolean[256];
+        for (int i = 0; i < 256; i++) {
+            removeable[i] = Character.isWhitespace(i);
+        }
+        removeable['"'] = true;
+    }
+
+    private boolean isRemoveable(char ch) {
+        return ch < 256 ? removeable[ch] : Character.isWhitespace(ch);
+    }
+
     public static VersionRange parseVersionRange( String val ) throws IllegalArgumentException, NumberFormatException
     {
         if ( val == null || val.trim().length() == 0 )