Fixes #353862 (Improve performance of QuotedStringTokenizer.quote()).

This commit is contained in:
Simone Bordet 2011-08-04 12:15:39 +02:00
parent 3d9ebd7803
commit 01cbaf528b
2 changed files with 134 additions and 149 deletions

View File

@ -14,7 +14,8 @@ jetty-7.5.0-SNAPSHOT
+ 353210 Bundle-Version in o.e.j.o.boot.logback fix + 353210 Bundle-Version in o.e.j.o.boot.logback fix
+ 353465 JAASLoginService ignores callbackHandlerClass + 353465 JAASLoginService ignores callbackHandlerClass
+ 353563 HttpDestinationQueueTest too slow + 353563 HttpDestinationQueueTest too slow
+ 353862 Improve performance of QuotedStringTokenizer.quote()
jetty-7.4.4.v20110707 July 7th 2011 jetty-7.4.4.v20110707 July 7th 2011
+ 308851 Converted all jetty-client module tests to JUnit 4 + 308851 Converted all jetty-client module tests to JUnit 4
+ 345268 JDBCSessionManager does not work with maxInactiveInterval = -1 + 345268 JDBCSessionManager does not work with maxInactiveInterval = -1

View File

@ -4,16 +4,17 @@
// All rights reserved. This program and the accompanying materials // All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0 // are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution. // and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at // The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html // http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at // The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php // http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses. // You may elect to redistribute this code under either of these licenses.
// ======================================================================== // ========================================================================
package org.eclipse.jetty.util; package org.eclipse.jetty.util;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -27,7 +28,7 @@ import java.util.StringTokenizer;
* Quotes can be escaped with '\'. * Quotes can be escaped with '\'.
* *
* @see java.util.StringTokenizer * @see java.util.StringTokenizer
* *
*/ */
public class QuotedStringTokenizer public class QuotedStringTokenizer
extends StringTokenizer extends StringTokenizer
@ -43,7 +44,7 @@ public class QuotedStringTokenizer
private int _lastStart=0; private int _lastStart=0;
private boolean _double=true; private boolean _double=true;
private boolean _single=true; private boolean _single=true;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public QuotedStringTokenizer(String str, public QuotedStringTokenizer(String str,
String delim, String delim,
@ -56,11 +57,11 @@ public class QuotedStringTokenizer
_delim=delim; _delim=delim;
_returnDelimiters=returnDelimiters; _returnDelimiters=returnDelimiters;
_returnQuotes=returnQuotes; _returnQuotes=returnQuotes;
if (_delim.indexOf('\'')>=0 || if (_delim.indexOf('\'')>=0 ||
_delim.indexOf('"')>=0) _delim.indexOf('"')>=0)
throw new Error("Can't use quotes as delimiters: "+_delim); throw new Error("Can't use quotes as delimiters: "+_delim);
_token=new StringBuffer(_string.length()>1024?512:_string.length()/2); _token=new StringBuffer(_string.length()>1024?512:_string.length()/2);
} }
@ -71,7 +72,7 @@ public class QuotedStringTokenizer
{ {
this(str,delim,returnDelimiters,false); this(str,delim,returnDelimiters,false);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public QuotedStringTokenizer(String str, public QuotedStringTokenizer(String str,
String delim) String delim)
@ -92,15 +93,15 @@ public class QuotedStringTokenizer
// Already found a token // Already found a token
if (_hasToken) if (_hasToken)
return true; return true;
_lastStart=_i; _lastStart=_i;
int state=0; int state=0;
boolean escape=false; boolean escape=false;
while (_i<_string.length()) while (_i<_string.length())
{ {
char c=_string.charAt(_i++); char c=_string.charAt(_i++);
switch (state) switch (state)
{ {
case 0: // Start case 0: // Start
@ -130,8 +131,8 @@ public class QuotedStringTokenizer
_hasToken=true; _hasToken=true;
state=1; state=1;
} }
continue; break;
case 1: // Token case 1: // Token
_hasToken=true; _hasToken=true;
if(_delim.indexOf(c)>=0) if(_delim.indexOf(c)>=0)
@ -153,10 +154,11 @@ public class QuotedStringTokenizer
state=3; state=3;
} }
else else
{
_token.append(c); _token.append(c);
continue; }
break;
case 2: // Single Quote case 2: // Single Quote
_hasToken=true; _hasToken=true;
if (escape) if (escape)
@ -177,10 +179,11 @@ public class QuotedStringTokenizer
escape=true; escape=true;
} }
else else
{
_token.append(c); _token.append(c);
continue; }
break;
case 3: // Double Quote case 3: // Double Quote
_hasToken=true; _hasToken=true;
if (escape) if (escape)
@ -201,8 +204,10 @@ public class QuotedStringTokenizer
escape=true; escape=true;
} }
else else
{
_token.append(c); _token.append(c);
continue; }
break;
} }
} }
@ -212,7 +217,7 @@ public class QuotedStringTokenizer
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public String nextToken() public String nextToken()
throws NoSuchElementException throws NoSuchElementException
{ {
if (!hasMoreTokens() || _token==null) if (!hasMoreTokens() || _token==null)
throw new NoSuchElementException(); throw new NoSuchElementException();
@ -225,7 +230,7 @@ public class QuotedStringTokenizer
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public String nextToken(String delim) public String nextToken(String delim)
throws NoSuchElementException throws NoSuchElementException
{ {
_delim=delim; _delim=delim;
_i=_lastStart; _i=_lastStart;
@ -244,7 +249,7 @@ public class QuotedStringTokenizer
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@Override @Override
public Object nextElement() public Object nextElement()
throws NoSuchElementException throws NoSuchElementException
{ {
return nextToken(); return nextToken();
} }
@ -258,13 +263,14 @@ public class QuotedStringTokenizer
return -1; return -1;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Quote a string. /** Quote a string.
* The string is quoted only if quoting is required due to * The string is quoted only if quoting is required due to
* embeded delimiters, quote characters or the * embedded delimiters, quote characters or the
* empty string. * empty string.
* @param s The string to quote. * @param s The string to quote.
* @param delim the delimiter to use to quote the string
* @return quoted string * @return quoted string
*/ */
public static String quoteIfNeeded(String s, String delim) public static String quoteIfNeeded(String s, String delim)
@ -274,7 +280,7 @@ public class QuotedStringTokenizer
if (s.length()==0) if (s.length()==0)
return "\"\""; return "\"\"";
for (int i=0;i<s.length();i++) for (int i=0;i<s.length();i++)
{ {
char c = s.charAt(i); char c = s.charAt(i);
@ -285,7 +291,7 @@ public class QuotedStringTokenizer
return b.toString(); return b.toString();
} }
} }
return s; return s;
} }
@ -303,81 +309,73 @@ public class QuotedStringTokenizer
return null; return null;
if (s.length()==0) if (s.length()==0)
return "\"\""; return "\"\"";
StringBuffer b=new StringBuffer(s.length()+8); StringBuffer b=new StringBuffer(s.length()+8);
quote(b,s); quote(b,s);
return b.toString(); return b.toString();
}
private static final char[] escapes = new char[31];
static
{
Arrays.fill(escapes, (char)-1);
escapes['\b'] = 'b';
escapes['\t'] = 't';
escapes['\n'] = 'n';
escapes['\f'] = 'f';
escapes['\r'] = 'r';
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Quote a string into an Appendable. /** Quote a string into an Appendable.
* The characters ", \, \n, \r, \t, \f and \b are escaped * The characters ", \, \n, \r, \t, \f and \b are escaped
* @param buf The Appendable * @param buffer The Appendable
* @param s The String to quote. * @param input The String to quote.
*/ */
public static void quote(Appendable buf, String s) public static void quote(Appendable buffer, String input)
{ {
try try
{ {
buf.append('"'); buffer.append('"');
for (int i = 0; i < input.length(); ++i)
for (int i=0;i<s.length();i++)
{ {
char c = s.charAt(i); char c = input.charAt(i);
switch(c) if (c >= 32)
{ {
case '"': if (c == '"' || c == '\\')
buf.append("\\\""); buffer.append('\\');
continue; buffer.append(c);
case '\\': }
buf.append("\\\\"); else
continue; {
case '\n': char escape = escapes[c];
buf.append("\\n"); if (escape == -1)
continue; {
case '\r': // Unicode escape
buf.append("\\r"); buffer.append('\\').append('0').append('0');
continue; if (c < 0x10)
case '\t': buffer.append('0');
buf.append("\\t"); buffer.append(Integer.toString(c, 16));
continue; }
case '\f': else
buf.append("\\f"); {
continue; buffer.append('\\').append(escape);
case '\b': }
buf.append("\\b");
continue;
default:
if (c<0x10)
{
buf.append("\\u000");
buf.append(Integer.toString(c,16));
}
else if (c<=0x1f)
{
buf.append("\\u00");
buf.append(Integer.toString(c,16));
}
else
buf.append(c);
continue;
} }
} }
buffer.append('"');
buf.append('"'); }
} catch (IOException x)
catch(IOException e)
{ {
throw new RuntimeException(e); throw new RuntimeException(x);
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Quote a string into a StringBuffer only if needed. /** Quote a string into a StringBuffer only if needed.
* Quotes are forced if any delim characters are present. * Quotes are forced if any delim characters are present.
* *
* @param buf The StringBuffer * @param buf The StringBuffer
* @param s The String to quote. * @param s The String to quote.
* @param delim String of characters that must be quoted. * @param delim String of characters that must be quoted.
@ -394,7 +392,7 @@ public class QuotedStringTokenizer
return true; return true;
} }
} }
try try
{ {
buf.append(s); buf.append(s);
@ -405,7 +403,7 @@ public class QuotedStringTokenizer
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Unquote a string. /** Unquote a string.
* @param s The string to unquote. * @param s The string to unquote.
@ -422,68 +420,66 @@ public class QuotedStringTokenizer
char last=s.charAt(s.length()-1); char last=s.charAt(s.length()-1);
if (first!=last || (first!='"' && first!='\'')) if (first!=last || (first!='"' && first!='\''))
return s; return s;
StringBuffer b=new StringBuffer(s.length()-2);
synchronized(b)
{
boolean escape=false;
for (int i=1;i<s.length()-1;i++)
{
char c = s.charAt(i);
if (escape) StringBuilder b = new StringBuilder(s.length() - 2);
boolean escape=false;
for (int i=1;i<s.length()-1;i++)
{
char c = s.charAt(i);
if (escape)
{
escape=false;
switch (c)
{ {
escape=false; case 'n':
switch (c) b.append('\n');
{ break;
case 'n': case 'r':
b.append('\n'); b.append('\r');
break; break;
case 'r': case 't':
b.append('\r'); b.append('\t');
break; break;
case 't': case 'f':
b.append('\t'); b.append('\f');
break; break;
case 'f': case 'b':
b.append('\f'); b.append('\b');
break; break;
case 'b': case '\\':
b.append('\b'); b.append('\\');
break; break;
case '\\': case '/':
b.append('\\'); b.append('/');
break; break;
case '/': case '"':
b.append('/'); b.append('"');
break; break;
case '"': case 'u':
b.append('"'); b.append((char)(
break; (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+
case 'u': (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+
b.append((char)( (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+
(TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+ (TypeUtil.convertHexDigit((byte)s.charAt(i++)))
(TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+ )
(TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+ );
(TypeUtil.convertHexDigit((byte)s.charAt(i++))) break;
) default:
); b.append(c);
break;
default:
b.append(c);
}
} }
else if (c=='\\')
{
escape=true;
continue;
}
else
b.append(c);
} }
else if (c=='\\')
return b.toString(); {
escape=true;
}
else
{
b.append(c);
}
} }
return b.toString();
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -522,15 +518,3 @@ public class QuotedStringTokenizer
_single=single; _single=single;
} }
} }