Mercurial Hosting > luan
diff src/org/eclipse/jetty/util/QuotedStringTokenizer.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/util/QuotedStringTokenizer.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,603 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util; + +import java.io.IOException; +import java.util.Arrays; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + +/* ------------------------------------------------------------ */ +/** StringTokenizer with Quoting support. + * + * This class is a copy of the java.util.StringTokenizer API and + * the behaviour is the same, except that single and double quoted + * string values are recognised. + * Delimiters within quotes are not considered delimiters. + * Quotes can be escaped with '\'. + * + * @see java.util.StringTokenizer + * + */ +public class QuotedStringTokenizer + extends StringTokenizer +{ + private final static String __delim="\t\n\r"; + private String _string; + private String _delim = __delim; + private boolean _returnQuotes=false; + private boolean _returnDelimiters=false; + private StringBuffer _token; + private boolean _hasToken=false; + private int _i=0; + private int _lastStart=0; + private boolean _double=true; + private boolean _single=true; + + /* ------------------------------------------------------------ */ + public QuotedStringTokenizer(String str, + String delim, + boolean returnDelimiters, + boolean returnQuotes) + { + super(""); + _string=str; + if (delim!=null) + _delim=delim; + _returnDelimiters=returnDelimiters; + _returnQuotes=returnQuotes; + + if (_delim.indexOf('\'')>=0 || + _delim.indexOf('"')>=0) + throw new Error("Can't use quotes as delimiters: "+_delim); + + _token=new StringBuffer(_string.length()>1024?512:_string.length()/2); + } + + /* ------------------------------------------------------------ */ + public QuotedStringTokenizer(String str, + String delim, + boolean returnDelimiters) + { + this(str,delim,returnDelimiters,false); + } + + /* ------------------------------------------------------------ */ + public QuotedStringTokenizer(String str, + String delim) + { + this(str,delim,false,false); + } + + /* ------------------------------------------------------------ */ + public QuotedStringTokenizer(String str) + { + this(str,null,false,false); + } + + /* ------------------------------------------------------------ */ + @Override + public boolean hasMoreTokens() + { + // Already found a token + if (_hasToken) + return true; + + _lastStart=_i; + + int state=0; + boolean escape=false; + while (_i<_string.length()) + { + char c=_string.charAt(_i++); + + switch (state) + { + case 0: // Start + if(_delim.indexOf(c)>=0) + { + if (_returnDelimiters) + { + _token.append(c); + return _hasToken=true; + } + } + else if (c=='\'' && _single) + { + if (_returnQuotes) + _token.append(c); + state=2; + } + else if (c=='\"' && _double) + { + if (_returnQuotes) + _token.append(c); + state=3; + } + else + { + _token.append(c); + _hasToken=true; + state=1; + } + break; + + case 1: // Token + _hasToken=true; + if(_delim.indexOf(c)>=0) + { + if (_returnDelimiters) + _i--; + return _hasToken; + } + else if (c=='\'' && _single) + { + if (_returnQuotes) + _token.append(c); + state=2; + } + else if (c=='\"' && _double) + { + if (_returnQuotes) + _token.append(c); + state=3; + } + else + { + _token.append(c); + } + break; + + case 2: // Single Quote + _hasToken=true; + if (escape) + { + escape=false; + _token.append(c); + } + else if (c=='\'') + { + if (_returnQuotes) + _token.append(c); + state=1; + } + else if (c=='\\') + { + if (_returnQuotes) + _token.append(c); + escape=true; + } + else + { + _token.append(c); + } + break; + + case 3: // Double Quote + _hasToken=true; + if (escape) + { + escape=false; + _token.append(c); + } + else if (c=='\"') + { + if (_returnQuotes) + _token.append(c); + state=1; + } + else if (c=='\\') + { + if (_returnQuotes) + _token.append(c); + escape=true; + } + else + { + _token.append(c); + } + break; + } + } + + return _hasToken; + } + + /* ------------------------------------------------------------ */ + @Override + public String nextToken() + throws NoSuchElementException + { + if (!hasMoreTokens() || _token==null) + throw new NoSuchElementException(); + String t=_token.toString(); + _token.setLength(0); + _hasToken=false; + return t; + } + + /* ------------------------------------------------------------ */ + @Override + public String nextToken(String delim) + throws NoSuchElementException + { + _delim=delim; + _i=_lastStart; + _token.setLength(0); + _hasToken=false; + return nextToken(); + } + + /* ------------------------------------------------------------ */ + @Override + public boolean hasMoreElements() + { + return hasMoreTokens(); + } + + /* ------------------------------------------------------------ */ + @Override + public Object nextElement() + throws NoSuchElementException + { + return nextToken(); + } + + /* ------------------------------------------------------------ */ + /** Not implemented. + */ + @Override + public int countTokens() + { + return -1; + } + + + /* ------------------------------------------------------------ */ + /** Quote a string. + * The string is quoted only if quoting is required due to + * embedded delimiters, quote characters or the + * empty string. + * @param s The string to quote. + * @param delim the delimiter to use to quote the string + * @return quoted string + */ + public static String quoteIfNeeded(String s, String delim) + { + if (s==null) + return null; + if (s.length()==0) + return "\"\""; + + + for (int i=0;i<s.length();i++) + { + char c = s.charAt(i); + if (c=='\\' || c=='"' || c=='\'' || Character.isWhitespace(c) || delim.indexOf(c)>=0) + { + StringBuffer b=new StringBuffer(s.length()+8); + quote(b,s); + return b.toString(); + } + } + + return s; + } + + /* ------------------------------------------------------------ */ + /** Quote a string. + * The string is quoted only if quoting is required due to + * embeded delimiters, quote characters or the + * empty string. + * @param s The string to quote. + * @return quoted string + */ + public static String quote(String s) + { + if (s==null) + return null; + if (s.length()==0) + return "\"\""; + + StringBuffer b=new StringBuffer(s.length()+8); + quote(b,s); + return b.toString(); + + } + + private static final char[] escapes = new char[32]; + static + { + Arrays.fill(escapes, (char)0xFFFF); + escapes['\b'] = 'b'; + escapes['\t'] = 't'; + escapes['\n'] = 'n'; + escapes['\f'] = 'f'; + escapes['\r'] = 'r'; + } + + /* ------------------------------------------------------------ */ + /** Quote a string into an Appendable. + * The characters ", \, \n, \r, \t, \f and \b are escaped + * @param buffer The Appendable + * @param input The String to quote. + */ + public static void quote(Appendable buffer, String input) + { + try + { + buffer.append('"'); + for (int i = 0; i < input.length(); ++i) + { + char c = input.charAt(i); + if (c >= 32) + { + if (c == '"' || c == '\\') + buffer.append('\\'); + buffer.append(c); + } + else + { + char escape = escapes[c]; + if (escape == 0xFFFF) + { + // Unicode escape + buffer.append('\\').append('u').append('0').append('0'); + if (c < 0x10) + buffer.append('0'); + buffer.append(Integer.toString(c, 16)); + } + else + { + buffer.append('\\').append(escape); + } + } + } + buffer.append('"'); + } + catch (IOException x) + { + throw new RuntimeException(x); + } + } + + /* ------------------------------------------------------------ */ + /** Quote a string into a StringBuffer only if needed. + * Quotes are forced if any delim characters are present. + * + * @param buf The StringBuffer + * @param s The String to quote. + * @param delim String of characters that must be quoted. + * @return true if quoted; + */ + public static boolean quoteIfNeeded(Appendable buf, String s,String delim) + { + for (int i=0;i<s.length();i++) + { + char c = s.charAt(i); + if (delim.indexOf(c)>=0) + { + quote(buf,s); + return true; + } + } + + try + { + buf.append(s); + return false; + } + catch(IOException e) + { + throw new RuntimeException(e); + } + } + + + /* ------------------------------------------------------------ */ + public static String unquoteOnly(String s) + { + return unquoteOnly(s, false); + } + + + /* ------------------------------------------------------------ */ + /** Unquote a string, NOT converting unicode sequences + * @param s The string to unquote. + * @param lenient if true, will leave in backslashes that aren't valid escapes + * @return quoted string + */ + public static String unquoteOnly(String s, boolean lenient) + { + if (s==null) + return null; + if (s.length()<2) + return s; + + char first=s.charAt(0); + char last=s.charAt(s.length()-1); + if (first!=last || (first!='"' && first!='\'')) + return s; + + 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; + if (lenient && !isValidEscaping(c)) + { + b.append('\\'); + } + b.append(c); + } + else if (c=='\\') + { + escape=true; + } + else + { + b.append(c); + } + } + + return b.toString(); + } + + /* ------------------------------------------------------------ */ + public static String unquote(String s) + { + return unquote(s,false); + } + + /* ------------------------------------------------------------ */ + /** Unquote a string. + * @param s The string to unquote. + * @return quoted string + */ + public static String unquote(String s, boolean lenient) + { + if (s==null) + return null; + if (s.length()<2) + return s; + + char first=s.charAt(0); + char last=s.charAt(s.length()-1); + if (first!=last || (first!='"' && first!='\'')) + return s; + + 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) + { + case 'n': + b.append('\n'); + break; + case 'r': + b.append('\r'); + break; + case 't': + b.append('\t'); + break; + case 'f': + b.append('\f'); + break; + case 'b': + b.append('\b'); + break; + case '\\': + b.append('\\'); + break; + case '/': + b.append('/'); + break; + case '"': + b.append('"'); + break; + case 'u': + b.append((char)( + (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<24)+ + (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<16)+ + (TypeUtil.convertHexDigit((byte)s.charAt(i++))<<8)+ + (TypeUtil.convertHexDigit((byte)s.charAt(i++))) + ) + ); + break; + default: + if (lenient && !isValidEscaping(c)) + { + b.append('\\'); + } + b.append(c); + } + } + else if (c=='\\') + { + escape=true; + } + else + { + b.append(c); + } + } + + return b.toString(); + } + + + /* ------------------------------------------------------------ */ + /** Check that char c (which is preceded by a backslash) is a valid + * escape sequence. + * @param c + * @return + */ + private static boolean isValidEscaping(char c) + { + return ((c == 'n') || (c == 'r') || (c == 't') || + (c == 'f') || (c == 'b') || (c == '\\') || + (c == '/') || (c == '"') || (c == 'u')); + } + + /* ------------------------------------------------------------ */ + /** + * @return handle double quotes if true + */ + public boolean getDouble() + { + return _double; + } + + /* ------------------------------------------------------------ */ + /** + * @param d handle double quotes if true + */ + public void setDouble(boolean d) + { + _double=d; + } + + /* ------------------------------------------------------------ */ + /** + * @return handle single quotes if true + */ + public boolean getSingle() + { + return _single; + } + + /* ------------------------------------------------------------ */ + /** + * @param single handle single quotes if true + */ + public void setSingle(boolean single) + { + _single=single; + } +}