Optimize / Cleanup QueryStringDecoder / QueryStringEncoder

Motivation:

QueryStringDecoder and QueryStringEncoder contained some code that could either cleaned-up or optimized.

Modifications:

- Fix typos in exception messages and javadocs
- Precompile Pattern
- Make use of StringUtil.EMPTY_STRING

Result:

Faster and cleaner code.
This commit is contained in:
Norman Maurer 2017-02-27 10:49:40 +01:00
parent ca2c349a4a
commit d675febf07
2 changed files with 27 additions and 42 deletions

View File

@ -26,6 +26,10 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static io.netty.util.internal.ObjectUtil.checkPositive;
import static io.netty.util.internal.StringUtil.EMPTY_STRING;
/**
* Splits an HTTP query string into a path string and key-value parameter pairs.
* This decoder is for one time use only. Create a new instance for each URI:
@ -102,16 +106,9 @@ public class QueryStringDecoder {
* specified charset.
*/
public QueryStringDecoder(String uri, Charset charset, boolean hasPath, int maxParams) {
if (uri == null) {
throw new NullPointerException("getUri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
if (maxParams <= 0) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}
checkNotNull(uri, "uri");
checkNotNull(charset, "charset");
checkPositive(maxParams, "maxParams");
this.uri = uri;
this.charset = charset;
@ -140,26 +137,19 @@ public class QueryStringDecoder {
* specified charset.
*/
public QueryStringDecoder(URI uri, Charset charset, int maxParams) {
if (uri == null) {
throw new NullPointerException("getUri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
if (maxParams <= 0) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}
checkNotNull(uri, "uri");
checkNotNull(charset, "charset");
checkPositive(maxParams, "maxParams");
String rawPath = uri.getRawPath();
if (rawPath != null) {
hasPath = true;
} else {
rawPath = "";
rawPath = EMPTY_STRING;
hasPath = false;
}
// Also take care of cut of things like "http://localhost"
this.uri = rawPath + (uri.getRawQuery() == null? "" : '?' + uri.getRawQuery());
this.uri = uri.getRawQuery() == null? rawPath : rawPath + '?' + uri.getRawQuery();
this.charset = charset;
this.maxParams = maxParams;
@ -178,10 +168,10 @@ public class QueryStringDecoder {
public String path() {
if (path == null) {
if (!hasPath) {
path = "";
path = EMPTY_STRING;
} else {
int pathEndPos = uri.indexOf('?');
path = decodeComponent(pathEndPos < 0 ? uri : uri.substring(0, pathEndPos), this.charset);
path = decodeComponent(pathEndPos < 0 ? uri : uri.substring(0, pathEndPos), charset);
}
}
return path;
@ -230,7 +220,7 @@ public class QueryStringDecoder {
// We haven't seen an `=' so far but moved forward.
// Must be a param of the form '&a&' so add it with
// an empty value.
if (!addParam(params, decodeComponent(s.substring(pos, i), charset), "")) {
if (!addParam(params, decodeComponent(s.substring(pos, i), charset), EMPTY_STRING)) {
return;
}
} else if (name != null) {
@ -245,7 +235,7 @@ public class QueryStringDecoder {
if (pos != i) { // Are there characters we haven't dealt with?
if (name == null) { // Yes and we haven't seen any `='.
addParam(params, decodeComponent(s.substring(pos, i), charset), "");
addParam(params, decodeComponent(s.substring(pos, i), charset), EMPTY_STRING);
} else { // Yes and this must be the last value.
addParam(params, name, decodeComponent(s.substring(pos, i), charset));
}
@ -308,7 +298,7 @@ public class QueryStringDecoder {
*/
public static String decodeComponent(final String s, final Charset charset) {
if (s == null) {
return "";
return EMPTY_STRING;
}
final int size = s.length();
boolean modified = false;

View File

@ -15,6 +15,8 @@
*/
package io.netty.handler.codec.http;
import io.netty.util.internal.ObjectUtil;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
@ -23,6 +25,7 @@ import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* Creates an URL-encoded URI from a path string and key-value parameter pairs.
@ -37,6 +40,7 @@ import java.util.List;
*/
public class QueryStringEncoder {
private static final Pattern PATTERN = Pattern.compile("+", Pattern.LITERAL);
private final Charset charset;
private final String uri;
private final List<Param> params = new ArrayList<Param>();
@ -54,31 +58,22 @@ public class QueryStringEncoder {
* path string in the specified charset.
*/
public QueryStringEncoder(String uri, Charset charset) {
if (uri == null) {
throw new NullPointerException("getUri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
this.uri = uri;
this.charset = charset;
this.uri = ObjectUtil.checkNotNull(uri, "uri");
this.charset = ObjectUtil.checkNotNull(charset, "charset");
}
/**
* Adds a parameter with the specified name and value to this encoder.
*/
public void addParam(String name, String value) {
if (name == null) {
throw new NullPointerException("name");
}
ObjectUtil.checkNotNull(name, "name");
params.add(new Param(name, value));
}
/**
* Returns the URL-encoded URI object which was created from the path string
* specified in the constructor and the parameters added by
* {@link #addParam(String, String)} getMethod.
* {@link #addParam(String, String)} method.
*/
public URI toUri() throws URISyntaxException {
return new URI(toString());
@ -87,7 +82,7 @@ public class QueryStringEncoder {
/**
* Returns the URL-encoded URI which was created from the path string
* specified in the constructor and the parameters added by
* {@link #addParam(String, String)} getMethod.
* {@link #addParam(String, String)} method.
*/
@Override
public String toString() {
@ -113,7 +108,7 @@ public class QueryStringEncoder {
private static String encodeComponent(String s, Charset charset) {
// TODO: Optimize me.
try {
return URLEncoder.encode(s, charset.name()).replace("+", "%20");
return URLEncoder.encode(s, PATTERN.matcher(charset.name()).replaceAll("%20"));
} catch (UnsupportedEncodingException ignored) {
throw new UnsupportedCharsetException(charset.name());
}