Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QueryParams which deprecates HttpParameters #2307

Merged
merged 49 commits into from
Dec 20, 2019
Merged
Changes from 1 commit
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
959f402
Add `QueryParams` which deprecates `HttpParameters`
trustin Dec 10, 2019
dfa5d11
Merge branch 'master' into immutable_http_params
trustin Dec 11, 2019
eb6bf37
Checkstyle
trustin Dec 11, 2019
8c47f62
Share the common logic between `QueryParamsBase` and `HttpHeadersBase`
trustin Dec 11, 2019
a70b113
Add some tests to ensure API consistency
trustin Dec 11, 2019
7863cca
Fix test failure
trustin Dec 11, 2019
6687a81
Rename a bunch of stuff for consistency
trustin Dec 11, 2019
acea7ff
Fix import
trustin Dec 11, 2019
48751d6
AbstractStringMultimapBuilder -> StringMultimapBuilder
trustin Dec 11, 2019
f7ae4e9
Add `QueryParamGetters.toQueryString()` and `appendQueryString()`
trustin Dec 12, 2019
5613b6d
Checkstyle and cleanup
trustin Dec 12, 2019
3f5a874
Documentation
trustin Dec 12, 2019
79ffa65
Add Javadoc return tag
trustin Dec 12, 2019
4a27a93
Merge branch 'master' into immutable_http_params
trustin Dec 14, 2019
c3ea71c
Address the comments from @anuraaga and @ikhoon
trustin Dec 14, 2019
b8c6d5e
Fix comment, inspired by @ikhoon's comment
trustin Dec 14, 2019
3663f03
Checkstyle
trustin Dec 14, 2019
b365e6d
Clean-up
trustin Dec 15, 2019
df1a365
Address the comments from @minwoox
trustin Dec 16, 2019
a041106
Address one more comment from @minwoox
trustin Dec 16, 2019
c5c096a
Address yet another comment from @minwoox
trustin Dec 16, 2019
7eea42f
Address some of the comments from @anuraaga
trustin Dec 16, 2019
39521ff
Replace `ThreadLocalByteArray` with `TemporaryThreadLocals` / Optimiz…
trustin Dec 16, 2019
ce90fe5
Optimization
trustin Dec 17, 2019
bfd2196
Simplify
trustin Dec 17, 2019
0ef906b
Clean-up
trustin Dec 18, 2019
1bc56ae
Fix encoder bug / Optimize decoder / More tests
trustin Dec 18, 2019
b8c5e91
Add benchmark for `QueryStringDecoder`
trustin Dec 18, 2019
937779c
Switch to traditional decoding loop as advised by @anuraaga
trustin Dec 18, 2019
2cac19f
Optimization and fix
trustin Dec 18, 2019
266cdc2
Further optimization of ASCII decoding
trustin Dec 18, 2019
9240e84
Optimize the decoder tad bit more, allowing us to win at any case
trustin Dec 18, 2019
b4956d0
Slightly more compact lookup table
trustin Dec 18, 2019
47f448d
Use `hashName()` instead of `.hashCode()` for names
trustin Dec 18, 2019
1e78f95
Clean-up benchmarks and add test for long query string
trustin Dec 18, 2019
e44d3b3
Improve safe octet scanning in `QueryStringEncoder` as advised by @an…
trustin Dec 18, 2019
ba0e903
Optimize percent encoding
trustin Dec 18, 2019
3d9123c
Borrow more from Guava
trustin Dec 18, 2019
c67ffb7
Checkstyle
trustin Dec 18, 2019
541796b
Experiment: Pre-inflate `StringBuilder`
trustin Dec 18, 2019
fd1c4e5
Micro clean-up
trustin Dec 18, 2019
c399ff9
Checkstyle
trustin Dec 19, 2019
8383ef9
Experiment: Make `char[]` stack-allocated by JVM
trustin Dec 19, 2019
5d17e4a
Checkstyle
trustin Dec 19, 2019
959793f
Merge branches
trustin Dec 19, 2019
59b00d5
Add Guava copyright header
trustin Dec 19, 2019
5b7dfaf
Checkstyle
trustin Dec 19, 2019
1cb66cb
Address the comments from @anuraaga
trustin Dec 19, 2019
4ae61e4
Address the comments from @minwoox
trustin Dec 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Borrow more from Guava
  • Loading branch information
trustin committed Dec 18, 2019
commit 3d9123cd251e9e10597e0021f4824a2ba1efdbf8
127 changes: 50 additions & 77 deletions core/src/main/java/com/linecorp/armeria/common/QueryStringEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ final class QueryStringEncoder {
// Forked from netty-4.1.43.
// https://github.com/netty/netty/blob/bd8cea644a07890f5bada18ddff0a849b58cd861/codec-http/src/main/java/io/netty/handler/codec/http/QueryStringEncoder.java

private static final byte WRITE_UTF_UNKNOWN = (byte) '?';
private static final char[] CHAR_MAP = "0123456789ABCDEF".toCharArray();
private static final char[] UTF_UNKNOWN = { '%', '3', 'F' }; // Percent encoded question mark
private static final char[] UPPER_HEX_DIGITS = "0123456789ABCDEF".toCharArray();
private static final byte[] SAFE_OCTETS =
createSafeOctets("-_.*abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");

Expand Down Expand Up @@ -112,25 +112,40 @@ private static void encodeUtf8Component(TemporaryThreadLocals tempThreadLocals,

int i = start;
for (;;) {
final char c = s.charAt(i++);
char c = s.charAt(i++);
if (c < 0x80) {
if (c == ' ') {
buf.append('+');
} else {
appendEncoded(buf, tmp, c);
tmp[1] = UPPER_HEX_DIGITS[c >>> 4];
tmp[2] = UPPER_HEX_DIGITS[c & 0xF];
buf.append(tmp, 0, 3);
}
} else if (c < 0x800) {
appendEncoded(buf, tmp,
0xc0 | (c >> 6), 0x80 | (c & 0x3f));
tmp[5] = UPPER_HEX_DIGITS[c & 0xF];
c >>>= 4;
tmp[4] = UPPER_HEX_DIGITS[0x8 | (c & 0x3)];
c >>>= 2;
tmp[2] = UPPER_HEX_DIGITS[c & 0xF];
c >>>= 4;
tmp[1] = UPPER_HEX_DIGITS[0xC | c];
buf.append(tmp, 0, 6);
} else if (!StringUtil.isSurrogate(c)) {
appendEncoded(buf, tmp,
0xe0 | (c >> 12),
0x80 | ((c >> 6) & 0x3f),
0x80 | (c & 0x3f));
tmp[8] = UPPER_HEX_DIGITS[c & 0xF];
c >>>= 4;
tmp[7] = UPPER_HEX_DIGITS[0x8 | (c & 0x3)];
c >>>= 2;
tmp[5] = UPPER_HEX_DIGITS[c & 0xF];
c >>>= 4;
tmp[4] = UPPER_HEX_DIGITS[0x8 | (c & 0x3)];
c >>>= 2;
tmp[2] = UPPER_HEX_DIGITS[c & 0xF];
tmp[1] = 'E';
buf.append(tmp, 0, 9);
} else if (!Character.isHighSurrogate(c)) {
appendEncoded(buf, tmp, WRITE_UTF_UNKNOWN);
buf.append(UTF_UNKNOWN);
} else if (i == end) { // Surrogate Pair consumes 2 characters.
appendEncoded(buf, tmp, WRITE_UTF_UNKNOWN);
buf.append(UTF_UNKNOWN);
break;
} else {
// Extra method to allow inlining the rest of writeUtf8 which is the most likely code path.
Expand All @@ -155,77 +170,35 @@ private static void encodeUtf8Component(TemporaryThreadLocals tempThreadLocals,

private static void writeUtf8Surrogate(StringBuilder buf, char[] tmp, char c, char c2) {
if (!Character.isLowSurrogate(c2)) {
appendEncoded(buf, tmp,
WRITE_UTF_UNKNOWN,
Character.isHighSurrogate(c2) ? WRITE_UTF_UNKNOWN : c2);
buf.append(UTF_UNKNOWN);
if (Character.isHighSurrogate(c2)) {
buf.append(UTF_UNKNOWN);
} else {
tmp[1] = UPPER_HEX_DIGITS[c2 >>> 4];
tmp[2] = UPPER_HEX_DIGITS[c2 & 0xF];
buf.append(tmp, 0, 3);
}
return;
}

final int codePoint = Character.toCodePoint(c, c2);
int codePoint = Character.toCodePoint(c, c2);
// See http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G2630.
appendEncoded(buf, tmp,
0xf0 | (codePoint >> 18),
0x80 | ((codePoint >> 12) & 0x3f),
0x80 | ((codePoint >> 6) & 0x3f),
0x80 | (codePoint & 0x3f));
}

private static void appendEncoded(StringBuilder buf, char[] tmp, int b) {
setEncoded(tmp, b);
buf.append(tmp, 0, 3);
}

private static void appendEncoded(StringBuilder buf, char[] tmp, int b1, int b2) {
setEncoded(tmp, b1, b2);
buf.append(tmp, 0, 6);
}

private static void appendEncoded(StringBuilder buf, char[] tmp, int b1, int b2, int b3) {
setEncoded(tmp, b1, b2, b3);
buf.append(tmp, 0, 9);
}

private static void appendEncoded(StringBuilder buf, char[] tmp, int b1, int b2, int b3, int b4) {
setEncoded(tmp, b1, b2, b3, b4);
tmp[11] = UPPER_HEX_DIGITS[codePoint & 0xF];
codePoint >>>= 4;
tmp[10] = UPPER_HEX_DIGITS[0x8 | (codePoint & 0x3)];
codePoint >>>= 2;
tmp[8] = UPPER_HEX_DIGITS[codePoint & 0xF];
codePoint >>>= 4;
tmp[7] = UPPER_HEX_DIGITS[0x8 | (codePoint & 0x3)];
codePoint >>>= 2;
tmp[5] = UPPER_HEX_DIGITS[codePoint & 0xF];
codePoint >>>= 4;
tmp[4] = UPPER_HEX_DIGITS[0x8 | (codePoint & 0x3)];
codePoint >>>= 2;
tmp[2] = UPPER_HEX_DIGITS[codePoint & 0xF];
tmp[1] = 'F';
buf.append(tmp, 0, 12);
}

private static void setEncoded(char[] tmp, int b) {
tmp[1] = highDigit(b);
tmp[2] = lowDigit(b);
}

private static void setEncoded(char[] tmp, int b1, int b2) {
setEncoded(tmp, b1);
tmp[4] = highDigit(b2);
tmp[5] = lowDigit(b2);
}

private static void setEncoded(char[] tmp, int b1, int b2, int b3) {
setEncoded(tmp, b1, b2);
tmp[7] = highDigit(b3);
tmp[8] = lowDigit(b3);
}

private static void setEncoded(char[] tmp, int b1, int b2, int b3, int b4) {
setEncoded(tmp, b1, b2, b3);
tmp[10] = highDigit(b4);
tmp[11] = lowDigit(b4);
}

/**
* Convert the given digit to a upper hexadecimal char.
*
* @param digit the number to convert to a character.
* @return the {@code char} representation of the specified digit
* in hexadecimal.
*/
private static char highDigit(int digit) {
return CHAR_MAP[digit >>> 4];
}
private static char lowDigit(int digit) {
return CHAR_MAP[digit & 0xF];
}

private QueryStringEncoder() {}
}