improve jwt parser memory allocation

re-use buffer instead of creating new ones
avoid creating unneeded buffers in the Strings util methods
Stop continuously copying array with StringBuilder#deleteCharAt
work directly on StringBuilder instead of creating a temporary String

test added to cover the modified methods
This commit is contained in:
benoit 2016-08-31 16:39:42 +02:00
parent 0408313d3f
commit 9735d1ad98
3 changed files with 68 additions and 9 deletions

View File

@ -213,7 +213,8 @@ public class DefaultJwtParser implements JwtParser {
if (c == SEPARATOR_CHAR) { if (c == SEPARATOR_CHAR) {
String token = Strings.clean(sb.toString()); CharSequence tokenSeq = Strings.clean(sb);
String token = tokenSeq!=null?tokenSeq.toString():null;
if (delimiterCount == 0) { if (delimiterCount == 0) {
base64UrlEncodedHeader = token; base64UrlEncodedHeader = token;
@ -222,7 +223,7 @@ public class DefaultJwtParser implements JwtParser {
} }
delimiterCount++; delimiterCount++;
sb = new StringBuilder(128); sb.setLength(0);
} else { } else {
sb.append(c); sb.append(c);
} }

View File

@ -159,22 +159,38 @@ public final class Strings {
* @see java.lang.Character#isWhitespace * @see java.lang.Character#isWhitespace
*/ */
public static String trimWhitespace(String str) { public static String trimWhitespace(String str) {
return (String) trimWhitespace((CharSequence)str);
}
private static CharSequence trimWhitespace(CharSequence str) {
if (!hasLength(str)) { if (!hasLength(str)) {
return str; return str;
} }
StringBuilder sb = new StringBuilder(str); final int length = str.length();
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
sb.deleteCharAt(0); int start = 0;
while (start < length && Character.isWhitespace(str.charAt(start))) {
start++;
} }
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
sb.deleteCharAt(sb.length() - 1); int end = length;
while (start < length && Character.isWhitespace(str.charAt(end - 1))) {
end--;
} }
return sb.toString();
return ((start > 0) || (end < length)) ? str.subSequence(start, end) : str;
} }
public static String clean(String str) { public static String clean(String str) {
CharSequence result = clean((CharSequence) str);
return result!=null?result.toString():null;
}
public static CharSequence clean(CharSequence str) {
str = trimWhitespace(str); str = trimWhitespace(str);
if ("".equals(str)) { if (!hasLength(str)) {
return null; return null;
} }
return str; return str;

View File

@ -14,4 +14,46 @@ class StringsTest {
assertTrue Strings.hasText(" foo "); assertTrue Strings.hasText(" foo ");
assertTrue Strings.hasText("foo") assertTrue Strings.hasText("foo")
} }
@Test
void testClean() {
assertEquals "this is a test", Strings.clean("this is a test")
assertEquals "this is a test", Strings.clean(" this is a test")
assertEquals "this is a test", Strings.clean(" this is a test ")
assertEquals "this is a test", Strings.clean("\nthis is a test \t ")
assertNull Strings.clean(null)
assertNull Strings.clean("")
assertNull Strings.clean("\t")
assertNull Strings.clean(" ")
}
@Test
void testCleanCharSequence() {
def result = Strings.clean(new StringBuilder("this is a test"))
assertNotNull result
assertEquals "this is a test", result.toString()
result = Strings.clean(new StringBuilder(" this is a test"))
assertNotNull result
assertEquals "this is a test", result.toString()
result = Strings.clean(new StringBuilder(" this is a test "))
assertNotNull result
assertEquals "this is a test", result.toString()
result = Strings.clean(new StringBuilder("\nthis is a test \t "))
assertNotNull result
assertEquals "this is a test", result.toString()
assertNull Strings.clean((StringBuilder) null)
assertNull Strings.clean(new StringBuilder(""))
assertNull Strings.clean(new StringBuilder("\t"))
assertNull Strings.clean(new StringBuilder(" "))
}
@Test
void testTrimWhitespace() {
assertEquals "", Strings.trimWhitespace(" ")
}
} }